Скачиваний:
61
Добавлен:
24.03.2015
Размер:
267.78 Кб
Скачать

Глава 11. Классы как типы

11.1. Объявление класса

Уже говорилось, что класс в языке С# играет две роли: это "контейнер" статических методов и статических полей и это "трафарет", позволяющий порождать конкретные объекты. Класс как контейнер нами уже подробно изучен.

Класс как трафарет - это библиотечный или определяемый программистом-пользователем тип данных. В английском языке для определённого программистом класса, играющего эту роль, используется краткое обозначение UDT - user-defined type. Сейчас будем рассматривать именно такие классы.

Класс, как определяемый пользователем тип, позволяет создавать конкретные объекты, состав и состояние каждого из которых задают нестатические поля класса, а поведение - его нестатические методы.

Достаточно общее определение (декларация иначе объявление) класса имеет следующий формат:

модификаторы_классаopt class имя_класса спецификация_базы_классаоpt тело_класса ;opt

Как мы уже говорили, индекс opt (от английского option - альтернатива, выбор) после элемента декларации указывает на необязательность предшествующего ему элемента. Даже точка с запятой после тела класса не является обязательной. Начнем изучение особенностей построения тех пользовательских классов, в определения которых входят только обязательные элементы и, возможно, модификаторы класса.

С учетом названных ограничений минимальный состав объявления класса таков:

модификаторы_классаоpt class имя_класса тело_класса

В декларации класса class - служебное слово, называемое ключом класса. Имя_класса - идентификатор, выбранный автором класса в качестве его имени.

Модификаторы_класса это:

- один из пяти уже неоднократно названных модификаторов доступа

(public, protected, internal, private, protected internal);

  • модификаторы, применяемые при вложении и наследовании классов (new, abstract, sealed - одновременное применение модификаторов sealed и abstract недопустимо);

  • static - модификатор статического класса.

При использовании нескольких модификаторов они отделяются друг от друга пробелами.

Тело_класса - заключенная в фигурные скобки последовательность объявлений (деклараций) членов класса. Объявление члена класса:

  • объявление константы;

  • объявление поля;

  • объявление метода;

  • объявление свойства;

  • объявление события;

  • объявление индексатора;

  • объявление операции;

  • объявление конструктора;

  • объявление финализатора;

  • объявление статического конструктора;

  • объявление типа.

Перечислив разновидности членов класса, будем вводить их в употребление по мере необходимости, и тогда же объяснять назначение и возможности каждого из них. Применяя в рассмотренных ранее программах библиотечные классы, мы использовали их методы, конструкторы, поля и свойства. На первом этапе знакомства с особенностями определения пользовательских классов ограничимся именно такими членами.

11.2. Поля объектов

Поле - это член объявления класса, представляющий переменные, связанные с классом или его объектом. Поля классов или статические поля мы уже рассмотрели. Сосредоточимся на особенностях нестатических полей, т.е. полей объектов. Объявление поля вводит одну или несколько переменных одного типа. Его формат:

модификаторы_поляopt тип_поля объявление_переменных;

Обратите внимание, что обязательными элементами объявления поля являются его тип и объявление переменных.

Тип_поля определяет тип вводимых этим полем переменных.

Объявление_переменных – это либо одно объявление, либо список объявлений, разделенных запятыми. Каждое объявление имеет один из следующих двух форматов: идентификатор или идентификатор = инициализатор_переменной

В свою очередь инициализатор переменной может быть либо выражением, в том числе и выражением, содержащем обращение к конструктору объектов, либо инициализатором массива. Инициализация переменных нестатических полей выполняется при создании объекта класса. Если в объявлении переменной инициализатор отсутствует, то переменная инициализируется по умолчанию значением, соответствующим ее типу.

В определении поля могут присутствовать в допустимых сочетаниях несколько модификаторов, которые в этом случае отделяются друг от друга пробелами. Мы уже использовали поля с модификатором static.

Кроме модификатора static уже рассмотрены модификаторы, определяющие доступность членов класса вне объявления класса (public -открытый, protected - защищенный, private - закрытый, internal -внутренний). Статус закрытого доступа получают все члены по умолчанию, когда в объявлении модификатор доступа отсутствует.

Как и для статических полей для полей объектов могут применяться модификаторы: readonly - только для чтения; volatile - подвержен внешним воздействиям; new - применяется при наследовании (см. главу 13).

Некоторый опыт применения библиотечных классов у нас уже имеется, поэтому следующий пример мини-программы с двумя классами, которые определил программист, не вызовет затруднений.

// 11_01.cs - поля объектов и класса

class Person

{

public static int year = 2009; // текущий год

public int age; // возраст

public string name; // имя

}

public static void Main()

{

Person who; // ссылка на объект класса

who = new Person(); // объект класса

who.name = "Юджин"; // имя

who.age = 19; // возраст

Console.WriteLine("Имя: {0}, Год рождения: {1}", who.name, Person.year - who.age);

}

Результат выполнения программы: Имя: Юджин, Год рождения: 1990

Класс Person включает одно статическое поле year (сегодняшний год) и два поля объектов age (возраст) и name (имя). В методе Main() класса Program создана ссылка who типа Person и связанный с ней объект. Так как поля класса Person открытые, то ссылка who даёт возможность присваивать полям объекта значения и получать их.

Важной особенностью (значение которой в дальнейшем будет показано, например, при создании связных списков, см. §11.5) является возможность объявить в классе поле, имеющее тип ссылки на объекты того же класса. Класс с таким полем приведён в следующей программе:

// 11_02.cs - ссылка с типом класса как поле объекта

class A

{

public int a = 2;

public int b = 3;

public A memb; // ссылка на объект класса А

}

public static void Main()

{

A one = new A();

one.a = 12;

one.b = one.a / one.b;

Console.WriteLine("one.a={0}", one.a);

Console.WriteLine("one.b={0}", one.b);

A two = new A();

two.memb = one;

Console.WriteLine("two.memb.a={0}", two.memb.a);

Console.WriteLine("two.memb.b={0}", two.memb.b);

}

Результат выполнения программы:

one.a=12

one.b=4

two.memb.a=12

two.memb.b=4

В классе А декларировано и по умолчанию инициализировано значением null поле memb - ссылка типа А. В методе Main() определены две ссылки на объекты класса А и ассоциированные с ними объекты. Полям one.а и one.b явно присвоены значения. Полю two.memb присвоено значение ссылки one и тем самым поле two.memb "настроено" на объект, адресуемый ссылкой one. Квалифицированные имена two.memb.а и two.memb.b позволяют получить полный доступ к полям one.а и one.b. Это подтверждают результаты выполнения программы.

Ссылка на объект класса может быть объявлена как статическое поле этого же класса. Следующая программа иллюстрирует эту возможность.

// 11_03.cs - ссылка с типом класса как статическое поле

class A

{

public int a = 2;

public int b = 3;

static public A smemb; // ссылка на объект класса А

}

public static void Main()

{

A two = new A();

A.smemb = two;

Console.WriteLine("A.smemb.a={0}", A.smemb.a);

Console.WriteLine("A.smemb.b={0}", A.smemb.b);

}

Результат выполнения программы:

A.smemb.a=2

A.smemb.b=3

Программа очень похожа на предыдущую - отличие заключается в том, что поле smemb статическое, поэтому для обращений используются квалифицированные имена с префиксом "А.".

Соседние файлы в папке Lekc_C#