Инкапсуляция |
Классы: основные понятия
Описание класса
Презентацию к данной лекции Вы можете скачать здесь.
Класс является типом данных, определяемым пользователем. Он должен представлять собой одну логическую сущность, например, являться моделью реального объекта или процесса. Элементами класса являются данные и функции, предназначенные для их обработки.
Описание класса содержит ключевое слово class, за которым следует его имя, а далее в фигурных скобках — тело класса, то есть список его элементов. Кроме того, для класса можно задать его базовые классы (предки) и ряд необязательных атрибутов и спецификаторов, определяющих различные характеристики класса:
[ атрибуты ] [ спецификаторы ] class имя_класса [ : предки ] тело_класса
Обязательными являются только ключевое слово class, имя и тело класса. Тело класса — это список описаний его элементов, заключенный в фигурные скобки. Список может быть пустым, если класс не содержит ни одного элемента. Таким образом, простейшее описание класса может выглядеть так:
class Demo {}
Спецификаторы определяют свойства класса, а также доступность класса для других элементов программы. Возможные значения спецификаторов перечислены в таблице 5.1. Класс можно описывать непосредственно внутри пространства имен или внутри другого класса. В последнем случае класс называется вложенным.
№ | Спецификатор | Описание |
---|---|---|
1 | new | Используется для вложенных классов. Задает новое описание класса взамен унаследованного от предка. Применяется в иерархиях объектов |
2 | public | Доступ не ограничен |
3 | protected | Используется для вложенных классов. Доступ только из элементов данного и производных классов |
4 | internal | Доступ только из данной программы (сборки) |
5 | protected internal | Доступ только из данного и производных классов или из данной программы (сборки) |
6 | private | Используется для вложенных классов. Доступ только из элементов класса, внутри которого описан данный класс |
7 | abstract | Абстрактный класс. Применяется в иерархиях объектов, рассматривается в главе 8 |
8 | sealed | Бесплодный класс. Применяется в иерархиях объектов, рассматривается в главе 8 |
9 | static | Статический класс. Введен в версию языка 2.0. Рассматривается в разделе "Конструкторы" |
Спецификаторы 2–6 называются спецификаторами доступа. Они определяют, откуда можно непосредственно обращаться к данному классу. Спецификаторы доступа могут присутствовать в описании только в вариантах, приведенных в таблице, а также могут комбинироваться с остальными спецификаторами.
Сейчас мы не будем изучать вложенные классы. Для остальных классов допускаются два спецификатора: public и internal (по умолчанию).
Класс является обобщенным понятием, определяющим характеристики и поведение некоторого множества конкретных объектов этого класса, называемых экземплярами, или объектами, класса. Объекты создаются явным или неявным образом, то есть либо программистом, либо системой. Программист создает экземпляр класса с помощью операции new, например:
Demo a = new Demo(); // создание экземпляра класса Demo Demo b = new Demo(); // создание другого экземпляра класса Demo
Для каждого объекта при его создании в памяти выделяется отдельная область, в которой хранятся его данные. Кроме того, в классе могут присутствовать статические элементы, которые существуют в единственном экземпляре для всех объектов класса. Часто статические данные называют данными класса, а остальные — данными экземпляра.
Функциональные элементы класса не тиражируются, то есть всегда хранятся в единственном экземпляре. Для работы с данными класса используются методы класса ( статические методы ), для работы с данными экземпляра — методы экземпляра, или просто методы.
Поля и методы являются основными элементами класса. Кроме того, в классе можно задавать целую гамму других элементов: свойства, события, индексаторы, операции, конструкторы, деструкторы, а также типы ( рис. 5.1).
Ниже приведено краткое описание всех элементов класса, изображенных на рисунке:
- Константы класса хранят неизменяемые значения, связанные с классом.
- Методы реализуют вычисления или другие действия, выполняемые классом или экземпляром.
- Свойства определяют характеристики класса в совокупности со способами их задания и получения, то есть методами записи и чтения.
- Конструкторы реализуют действия по инициализации экземпляров или класса в целом.
- Деструкторы определяют действия, которые необходимо выполнить до того, как объект будет уничтожен.
- Индексаторы обеспечивают возможность доступа к элементам класса по их порядковому номеру.
- Операции задают действия с объектами с помощью знаков операций.
- События определяют уведомления, которые может генерировать класс.
- Типы — это типы данных, внутренние по отношению к классу.
Прежде чем начать изучение элементов класса, необходимо поговорить о присваивании и сравнении объектов.
Механизм выполнения присваивания один и тот же для величин любого типа, как ссылочного, так и значимого, однако результаты различаются. При присваивании значения копируется значение, а при присваивании ссылки — ссылка, поэтому после присваивания одного объекта другому мы получим две ссылки, указывающие на одну и ту же область памяти ( рис. 5.2).
Аналогичная ситуация с операцией проверки на равенство. Величины значимого типа равны, если равны их значения. Величины ссылочного типа равны, если они ссылаются на одни и те же данные (на рисунке объекты b и c равны, но a не равно b даже при равенстве их значений или если они обе равны null ).
Данные: поля и константы
Данные, содержащиеся в классе, могут быть переменными или константами и задаются в соответствии с правилами, рассмотренными в разделах "Переменные" и "Именованные константы". Переменные, описанные в классе, называются полями класса. При описании элементов класса можно также указывать атрибуты и спецификаторы, задающие различные характеристики элементов. Синтаксис описания элемента данных:
[ атрибуты ] [ спецификаторы ] [ const ] тип имя [ = начальное_значение ]
Возможные спецификаторы полей и констант перечислены в таблице 5.2. Для констант можно использовать только спецификаторы 1–6.
По умолчанию элементы класса считаются закрытыми ( private ). Для полей класса этот вид доступа является предпочтительным. Все методы класса имеют непосредственный доступ к его закрытым полям.
Внимание
Поля, описанные со спецификатором static, а также константы существуют в единственном экземпляре для всех объектов класса, поэтому к ним обращаются не через имя экземпляра, а через имя класса. Если класс содержит только статические элементы, экземпляр класса создавать не требуется. Именно этим фактом мы пользовались во всех предыдущих листингах.
Обращение к полю класса выполняется с помощью операции доступа (точка). Справа от точки задается имя поля, слева — имя экземпляра для обычных полей или имя класса для статических. В листинге 5.1 приведен пример простого класса Demo и два способа обращения к его полям.
using System; namespace ConsoleApplication1 { class Demo { public int a = 1; // поле данных public const double c = 1.66; // константа public static string s = "Demo"; // статическое поле класса double y; // закрытое поле данных } class Class1 { static void Main() { Demo x = new Demo(); // создание экземпляра класса Demo Console.WriteLine( x.a ); // x.a - обращение к полю класса Console.WriteLine( Demo.c ); // Demo.c - обращение к константе Console.WriteLine( Demo.s ); // обращение к статическому полю } } }Листинг 5.1. Класс Demo, содержащий поля и константу
Поля со спецификатором readonly предназначены только для чтения. Установить значение такого поля можно либо при его описании, либо в конструкторе (конструкторы рассматриваются далее).