Г. Шилдт - Полный справочник по C# (1160789), страница 25
Текст из файла (страница 25)
Несмотря на то что очень простые классы могут включатьтолько код или только данные, большинство реальных классов содержат и то, и другое.Данные содержатся в переменных экземпляров, определяемых классом, а код — вметодах. Однако важно с самого начала отметить, что класс определяет также рядспециальных членов данных и методов-членов, например статические переменные,константы, конструкторы, деструкторы, индексаторы, события, операторы и свойства.Пока мы офаничимся рассмотрением переменных экземпляров и методов класса, а кконцу главы познакомимся с конструкторами и деструкторами.
Остальные типы членов класса описаны в последующих главах.Класс создается с помощью ключевого слова c l a s s . Общая форма определениякласса, который содержит только переменные экземпляров и методы, имеет следующий вид:class имя_класса {II Объявление переменных экземпляров.доступ тип переменная!;доступ тип переменная2;//. . .доступ тип переменнаяЫ;II Объявление методов.доступ тип_возврата метод 1 (параметры) {II тело методаГлава б.
Введение в классы, объекты и методы127доступ тип_возврата метод2{параметры) {// тело методадоступ тип_возврата методы {параметры)/I тело метода{Обратите внимание на то, что объявление каждой переменной и каждого методапредваряется элементом доступ.
Здесь элемент доступ означает спецификатор доступа (например, p u b l i c ) , который определяет, как к этому члену можно получить доступ. Как упоминалось в главе 2, члены класса могут быть закрытыми в рамках классаили более доступными. Спецификатор доступа определяет, какой именно разрешентип доступа.
Спецификатор доступа необязателен, и, если он не указан, подразумевается, что этот член закрыт ( p r i v a t e ) . Члены с закрытым доступом (закрытые члены)могут использоваться только другими членами своего класса. В примерах этой главывсе члены классов определяются как public-члены, а это значит, что их могут использовать все остальные составные части программного кода, даже те, которые определены вне класса. К рассмотрению спецификаторов доступа мы вернемся в главе 8.Несмотря на отсутствие специального синтаксического правила определения класса (его качественного и количественного состава), все же считается, что класс долженопределять только одну логическую сущность. Например, класс, в котором хранятсяимена лиц и их телефонные номера, не должен (по общепринятым меркам) также содержать информацию о среднем количестве осадков, циклах возникновения пятен наСолнце и прочую не связанную с конкретными лицами информацию.
Другими словами, правильно определенный класс должен содержать логически связанные данные.И наоборот, помещая в один класс логически несвязанные данные, вы рискуете деструктурировать свой код.Классы, которые мы использовали в этой книге до сих пор, содержали толькоодин метод — Main (). Вскоре мы узнаем, как создавать и другие методы. Однако заметьте, что в общей форме определения класса метод Main() не задан.
Он нужентолько в том случае, если определяемый класс является отправной точкой программы.Определение классаДля иллюстрации мы создадим класс, который инкапсулирует информацию о зданиях (домах, складских помещениях, офисах и пр.). В этом классе (назовем егоBuilding) будут храниться три элемента информации о зданиях (количество этажей,общая площадь и количество жильцов).Ниже представлена первая версия класса Building. В нем определены три переменные экземпляра: f l o o r s , a r e a и occupants. Обратите внимание на то, что классB u i l d i n g не содержит ни одного метода.
Поэтому пока его можно считать классом^данных. (В следующих разделах мы дополним его методами.)class Building {public int floors;// количество этажейpublic int area;// общая площадь основания зданияpublic int occupants; // количество жильцов}Переменные экземпляра, определенные в классе Building, иллюстрируют общийспособ их объявления. Формат объявления переменной экземпляра такой:доступ тип имя_переменной;128Часть I.
Язык С#Здесь элемент доступ представляет спецификатор доступа, элемент тип — тип переменной экземпляра, а элемент имя_пвременной — имя этой переменной. Такимобразом, если не считать спецификатор доступа, то переменная экземпляра объявляется так же, как локальная переменная. В классе Building все переменные экземпляра объявлены с использованием модификатора доступа p u b l i c , который, как упоминалось выше, позволяет получать к ним доступ со стороны кода, расположенногодаже вне класса Building.Определение c l a s s создает новый тип данных.
В данном случае этот новый типданных называется Building. Это имя можно использовать для объявления объектовтипа Building. Помните, что объявление c l a s s — это лишь описание типа; оно несоздает реальных объектов. Таким образом, предыдущий код не означает существования объектов типа Building.Чтобы реально создать объект класса Building, используйте, например, такую инструкцию:Building house = new B u i l d i n g ( ) ; // Создаем объект// типа B u i l d i n g .IПосле выполнения этой инструкции house станет экземпляром класса Building,т.е. обретет "физическую" реальность.
Подробно эту инструкцию мы рассмотрим ниже.При каждом создании экземпляра класса создается объект, который содержит собственную копию каждой переменной экземпляра, определенной этим классом. Такимобразом, каждый объект класса B u i l d i n g будет содержать собственные копии переменных экземпляра f l o o r s , a r e a и occupants. Для доступа к этим переменным используется оператор "точка" (.). Оператор "точка" связывает имя объекта с именемего члена. Общий формат этого оператора имеет такой вид:объект.членКак видите, объект указывается слева от оператора "точка", а его член — справа.Например, чтобы присвоить переменной floors значение 2, используйте следующуюинструкцию.I house.floors = 2;В общем случае оператор "точка" можно использовать для доступа как к переменным экземпляров, так и методам.Рассмотрим полную программу, в которой используется класс Building.// Программа, в которой используется класс Building.using System;c l a s s Building {public i n t f l o o r s ;// количество этажейpublic i n t area;// общая площадь основания зданияpublic i n t occupants; // количество жильцов}// Этот класс объявляет объект типа Building,class BuildingDemo {public static void Main() {Building house = new Building(); // Создание объекта// типа Building,int areaPP; // Площадь, приходящаяся на одного жильца.// Присваиваем значения полям в объекте house,house.occupants = 4;house.area = 2500;house.floors = 2;Глава 6.
Введение в классы, объекты и методы129// Вычисляем площадь, приходящуюся на одного жильца дома.areaPP = house.area / house.occupants;Console.WriteLine("Дом имеет:\n " +house.floors + " этажа\п " +house.occupants + " жильца\п " +house.area +" квадратных футов общей площади, из них\п " +areaPP + " приходится на одного человека");Эта программа состоит из двух классов: B u i l d i n g и BuildingDemo. Внутри классаBuildingDemo метод Main() сначала создает экземпляр класса B u i l d i n g с именемhouse, а затем получает доступ к переменным этого экземпляра house, присваиваяим конкретные значения и используя эти значения в вычислениях.
Важно понимать,что B u i l d i n g и BuildingDemo — это два отдельных класса. Единственная связь между ними состоит в том, что один класс создает экземпляр другого. Хотя это отдельныеклассы, код класса BuildingDemo может получать доступ к членам класса Building,поскольку они объявлены открытыми, т.е. public-членами. Если бы в их объявлениине было спецификатора доступа p u b l i c , доступ к ним ограничивался бы рамкамикласса Building, а класс BuildingDemo не имел бы возможности использовать их.Если предыдущую программу назвать U s e B u i l d i n g .
c s , то в результате ее компиляции будет создан файл UseBuilding.exe. Классы B u i l d i n g и BuildingDemo автоматически становятся составными частями этого исполняемого файла. При его выполнении получим такие результаты:Дом имеет:2 этажа4 жильца2500 квадратных футов общей площади, из них625 приходится на одного человекаВ действительности совсем не обязательно классам B u i l d i n g и BuildingDemo находиться в одном исходном файле. Можно поместить каждый класс в отдельный файли назвать эти файлы B u i l d i n g , cs и BuildingDemo.
cs, соответственно. После этогонеобходимо дать компилятору команду скомпилировать оба файла и скомпоновать их.гся этого можно использовать следующую командную строку:esc B u i l d i n g . c s BuildingDemo,csЕсли вы работаете в среде Visual Studio IDE, нужно поместить оба файла в проекти выполнить команду построения этого проекта.Прежде чем идти дальше, имеет смысл вспомнить основной принцип программирования классов: каждый объект класса имеет собственные копии переменных экземпляра, определенных в этом классе. Таким образом, содержимое переменных в одномобъекте может отличаться от содержимого аналогичных переменных в другом. Междудвумя объектами нет связи, за исключением того, что они являются объектами одногои того же типа.
Например, если у вас есть два объекта типа B u i l d i n g и каждый объект имеет свою копию переменных f l o o r s , a r e a и occupants, то содержимое соответствующих (одноименных) переменных этих двух экземпляров может быть разным.Следующая программа демонстрирует это.// Эта программа создает два объекта класса B u i l d i n g .Гu s i n g System;130Часть I.
Язык С#class Building {public int floors;// количество этажейpublic int area;// общая площадь основания зданияpublic int occupants; // количество жильцов// Этот класс объявляет два объекта типа Building,class BuildingDemo {public static void Main() {Building house = new Building();Building office - new BuildingO;int areaPP; // Площадь, приходящаяся на одного жильца.// Присваиваем значения полям в объекте house,house.occupants = 4 ;house.area = 2500;house.floors = 2 ;// Присваиваем значения полям в объекте office,office.occupants = 25;office.area = 4200;office.floors = 3;// Вычисляем площадь, приходящуюся на одного жильца.areaPP = house.area / house.occupants;Console.WriteLine("Дом имеет:\n " +house.floors + " этажа\п " +house.occupants + " жильца\п " +house.area +" квадратных футов общей площади, из них\п " +areaPP + " приходится на одного человека");Console.WriteLine();// Вычисляем площадь, приходящуюся на одного// работника офиса.areaPP = office.area / office.occupants;Console.WriteLine("Офис имеет:\n " +office.floors + " этажаХп " +office.occupants + " работниковХп " +office.area +" квадратных футов общей площади, из них\п " +areaPP + " приходится на одного человека");Вот каков результат выполнения этой программы:Дом имеет:2 этажа4 жильца2500 квадратных футов общей площади, из них625 приходится на одного человекаОфис имеет:3 этажа25 работников4200 квадратных футов общей площади, из них168 приходится на одного человекаГлава 6.
Введение в классы, объекты и методы131Как видите, данные о доме (содержащиеся в объекте house) совершенно не связаны с данными об офисе (содержащимися в объекте o f f i c e ) . Эта ситуация отображена на рис. 6.1.floorshouseofficeг2area2500occupants4floors3area4200occupants25Рис. 6.1. Переменные экземпляров не связаныСоздание объектовВ предыдущих программах с помощью следующей строки был объявлен объекттипа Building.I B u i l d i n g house = new B u i l d i n g ( ) ;Это объявление выполняет две функции.