Г. Шилдт - С# 3.0 Полное руководство. 2010 (1160798), страница 50
Текст из файла (страница 50)
*/ зсасус чо1б зсасусМеГЬ() ( Иопзсас№смесп(); // не подлежит компиляции! ) ) В данном случае попытка вызвать нестатический метод (т.е. метод экземпляра) из статического метода приводит к ошибке во время компиляции. Следует особо подчеркнуть, что из метода типа зсас1с нельзя вызывать методы экземпляра и получать доступ к переменным экземпляра его класса, как это обычно делается посредством объектов данного класса. И объясняется это тем, что без указания конкретного объекта переменная или метод экземпляра оказываются недоступными. Например, приведенный ниже фрагмент кода считается совершенно верным. с1азз МуС1азз ( // Нестатический метод.
чоьб Нопзсасусмесь() ( Сопзо1е.Игъгепппе("В методе Нопзсас1сМеГЬ()."); ) /* Нестатический метод может быть вызван из статического метода по ссылке на объект. */ рцнттс зсас1с чогп зсак1сМеГЬ(Мус1азз оЬ) ( Глава 8. Подробнее о методах и классах 249 оЬ.Нопзгагъсмегп(); // все верно! ) В данном примере метод мопбгагйсмегь () вызывается из метода згаг1смегь () по ссылке на объект оЬ типа МуС1азз. Поля типа згагйс не зависят от конкретного объекта, и поэтому они удобны для хранения информации, применимой ко всему классу. Ниже приведен пример программы, демонстрирующей подобную ситуацию.
В этой программе поле типа з гас х с служит для хранения количества существующих объектов. // Испольэовать поле типа ягаг1с для подсчета // экземпляров существующих объектов. иягпс эуягеш; с1аяя Соппг1пяг ( ягагъс Тпг соппг От // Инкрементировать подсчет, когда создается объект. рпЬ11с Соппг1пяг() ( соопг+ни ) // Декрементировать подсчет, когда уничтожается объект. -Соппг1пяг () ( соппс —: рчв11с ягагъс 1пг пегсоопг () ( геспгп соппс; ) с1аяз СоппСоешо ( ягагъс уоаб Маап () ( Соппг1пяг оЬт Гог(1пг 1=0) ь < 10( 1ьь) ( оЬ = пен Соппг1пяг(); Сопяо1е.иг1сеъгпе("Текущий подсчет: Соппг1пяг.бегсоппг())) Выполнение этой программы приводит к следующему результату: Текущий подсчетт 1 Текущий подсчет: 2 Текущий подсчет: 3 Текущий подсчетт 4 Текущий подсчетт 5 Текущий подсчет: б Текущий подсчет: 7 Текущий подсчет: 8 250 Часть (.
Язык Сф Текущий подсчет: 9 Текущий подсчет: 10 Всякий раз, когда создается объект типа соппс1пяс, инкрементируется поле соиле типа всасфс. но всякий раз, когда такой объект утилизируется, поле сопок декрементируется. Следовательно, поле сопле всегда содержит количество сушествуюших в настояший момент объектов. И это становится возможным только благодаря использованию поля типа ягаефс. Аналогичный подсчет нельзя организовать с помощью переменной экземпляра, поскольку он имеет отношение ко всему классу, а не только к конкретному экземпляру объекта этого класса.
Ниже приведен еше один пример применения статических членов класса. Ранее в этой главе было показано, как объекты создаются с помошью фабрики класса. В том примере фабрика была нестатическим методом, а это означало, что фабричный метод можно было вызывать только по ссылке на объект, который нужно было предварительно создать. Но фабрику класса лучше реализовать как метод типа яеаефс, что даст возможность вызывать этот фабричный метод, не создавая ненужный обьект. Именно это улучшение и отражено в приведенном ниже переделанном примере программы, реализующей фабрику класса. // Использовать статическую фабрику класса. пвьпч Зуягеит с1авв МуС1аяя ( Тпт.
а, Ьт // Создать фабрику для класса МуС1авя. якас1с роваьс МуС1аяя Гассогу(1пк 1, 1пк 9) ( МуС1аяв Г = пеи МуС1авв () ) Г.а = 1; Г.Ь = фт гегпгп г; // возвратить объект ) рон11с чо10 Бпои() ( Сопяо1е.игьгеъупе("а и Ь: " + а + " " + Ь)т ) ) с1авв Ма)кеоп)есся ( всасъс чоьб Маьп Н ( Тпг 1, 9) // Сформировать объекты, используя фабрику. йог(1=0, 9 10т 1 < 10т 1++ Э ) ( Мус1аяя оЬ = МуС1аяя.гассогу(1, ф)т // создать объект оЬ.эьои()) ) Сопво1е.игьгеъьпе()т ) ) Глава(), Подробнее о методах и классах 251 В этом варианте программы фабричный метод рассеку () вызывается по имени его класса в следующей строке кода: Мус1авв оЬ = МуС1авв.гасхоту(1, 9)т // создать объект Теперь нет необходимости создавать объект класса мус1азз перед тем, как пользоваться фабрикой этого класса. Статические конструкторы Конструктор можно также объявить как всас1с.
Статический конструктор, как правило, используется для инициализации компонентов, применяемых ко всему классу, а не к отдельному экземпляру объекта этого класса. Поэтому члены класса инициализируются статическим конструктором до создания каких-либо объектов этого класса. Ниже приведен простой пример применения статического конструктора. // Применить статический конструктор. чзгпч Вуззеих с1азв Сопв ( рчЬ11с всасхс хпо а1рпат рипгъс 1пк Ьекат // Статический конструктор. воаохс Сопв() ( а1рна = 99; Сопво1е.итгкевапе("В статическом конструкторе."); ) // конструктор экземпляра.
рпъ11с Сопв() ( Ьеоа = 100) Сопзо1е.нх1оецапе("В конструкторе экземпляра.")х ) с1азв Сопзпеио ( воаохс чохб Магп() ( Сопв оЬ = пен Сопв()) Сопзо1е.ик1кеь1пе("Сопя.а1рпа: " + Сопя.а1рпа)т Сопво1е.ик1ое11пе("оЬ.Ьеоах " + оЬ.Ьека)т ) ) При выполнении этого кода получается следующий результат: В статическом конструкторе. В конструкторе экземпляра. Сопв.а1рна: 99 оЬ.Ьеках 100 Обратите внимание на то, что конструктор типа всас1с вызывается автоматически, когда класс загружается впервые, причем до конструктора экземпляра. Из этого можно 252 часть (, язык сз сделать более общий вывод: статический конструктор должен выполняться до любого конструктора экземпляра.
Более того, у статических конструкторов отсутствуют модификаторы доступа — они пользуются доступом по умолчанию, а следовательно, их нельзя вызывать иа программы. Статические классы Начиная с версии С(т 2.0, появилась возможность объявлять класс типа яеагхс. Статический класс обладает двумя основными свойствами. Во-первых, объекты статического класса создавать нельзя. И во-вторых, статический класс должен содержать только статические члены.
Статический класс создается по приведенной ниже форме объявления класса, видоизмененной ключевым словом яеасхс. ягагхс с1аяя имя класса ( // В таком классе все члены должны быть объявлены как ягаг1с. Ведь если класс становится статическим, то это совсем не означает, что статическими становятся и все его члены. Статические классы применяются главным образом в двух случаях. Во-первых, статический класс требуется при создании метода расширения — нового средства, внедренного в версии СФ 3.0. Методы расширения связаны в основном с языком 1.1(ь((2 и поэтому подробнее рассматриваются в главе 19. И во-вторых, статический класс служит для хранения совокупности связанных друг с другом статических методов.
Именно это его применение и рассматривается ниже. В приведенном ниже примере программы класс Нивегхсрп типа яеаехс служит для хранения ряда статических методов, оперирующих числовым значением. А поскольку все члены класса нивег1срп объявлены как яьагхс, то этот класс также объявлен как зкасхс, чтобы исключить получение экземпляров его объектов. Таким образом, класс Нивегхсгп выполняет организационную роль, предоставляя удобные средства для груп- пирования логически связанных методов.
// Продемонстрировать применение статического класса. ияхпд зуягевт якасхс с1аяя Нивеггсгп ( // Возвратить обратное числовое значение. ягасхс риЬ11с ОоиЫе Кес1ргоса1(боиЫе пив) ( гегигп 1/пивт // Возвратить дробную часть числового значения. ягасгс риЫ1с боиЫе ГгасРагг(боиЬ1е пив) ( гесигп пив — (хпс) пиит // Возвратить логическое значение Ггие, если числовое // значение переменной пив окажется четным, ясасхс риЬ1ьс Ьоо1 1якчеп(т(оиЫе пив) ( . гесигп (пив я 2) == 0 ? Сгие . "Га1яе; // Возвратить логическое значение Ггие, если числовое Глава 8. Подробнее 0 методах и классах 263 // значение переменной пив окажется нечетным. якасхс рпЬ11с Ьоо1 1вос)б(бопЬ1е пив) ( гегигп !1вЕчеп(пав); ) ) 1 с1авя зсасасС1аяяпево ( вгасьс чогб Ма1п() ( Сопво1е.нг1сеъ1пе("Обратная величина числа 5 равна " т ИчвегасГп.кес1ргоса1(5.0))) Сопво1е.нгагеътпе("Дробная часть числа 4.234 равна " + НивегасГп.Ггасрагг(4.234)); 1г(ипвег1сгп.1вЕчеп(10)) Сопво1е.нгагеьапе("10 — четное число.")) 1г(ичвег1сгп.1яобб(5)) Сопяо1е.нгасеъапе("5 — нечетное число.") // Далее следует попытка создать экземпляр // объекта класса Нчвег1сгп, что может стать // причиной появления ошибки.
// НчвегасГп оЬ = лен Ипвег1сгп()> // Ошибка! ) ) Вот к какому результату приводит выполнение этой программы: Обратная величина числа 5 равна 0.2 Дробная часть числа 4.234 равна 0.234 10 — четное число. 5 — нечетное число. Обратите внимание на то, что последняя строка приведенной выше программы закомментирована. Класс Ипвегасрп является статическим, и поэтому любая попытка создать объект этого класса может привести к ошибке во время компиляции.
Ошибкой будет также считаться попытка сделать нестатическим член класса Нпвег1сГп. И последнее замечание! несмотря на то, что для статического класса не допускается наличие конструктора экземпляра, у него может быть статический конструктор. ГЛАВА Перегрузка операторов В языке СФ допускается определять назначение оператора по отношению к создаваемому классу Этот процесс называется перегрузкой операторов. Благодаря перегрузке расширяется сфера применения оператора в классе. При этом действие оператора полностью контролируется и может меняться в зависимости от конкретного класса.
Например, оператор + может использоваться для ввода объекта в связный список в одном классе, где определяется такой список, тогда как в другом классе его назначение может оказаться совершенно иным. Когда оператор перегружается, ни одно из его первоначальных назначений не теряется. Он просто выполняет еще одну, новую операцию относительно конкретного объекта. Поэтому перегрузка оператора +, например, для обработки связного списка не меняет его назначение по отношению к целым числам, т.е.
к их сложению. Главное преимушество перегрузки операторов заключается в том, что она позволяет плавно интегрировать класс нового типа в среду программирования. Подобного рода расширяемость типов является важной составляющей эффективности такого объектноориентированного языка программирования, как СФ. Как только для класса определяются операторы, появляется возможность оперировать объектами этого класса, используя обычный синтаксис выражений в С((.