👨🎓️ Самоучитель по C#: абстрактные классы и члены классов
Осваиваем на наглядных примерах базовые концепции языка C# – абстрактные классы и члены классов.
Абстрактные классы
Абстрактный класс похож на обычный класс. Он также может иметь переменные, методы, конструкторы, свойства. Единственное, что при определении абстрактных классов используется ключевое слово abstract
.
Модификатор abstract
:
- указывает, что реализация сущности с данным модификатором является неполной или отсутствует.
- может использоваться с классами, методами, свойствами, индексаторами и событиями.
- в объявлении класса указывает, что класс предназначен только для использования в качестве базового класса для других классов.
Члены, помеченные как абстрактные или включенные в абстрактный класс, должны быть реализованы с помощью классов, производных от абстрактных классов.
Например, определим абстрактный класс, который представляет некое транспортное средство:
Транспортное средство представляет некоторую абстракцию, которая не имеет конкретного воплощения. Например, есть легковые и грузовые машины, самолеты, морские суда, но как такового транспортного средства нет. Тем не менее все транспортные средства имеют нечто общее – они могут перемещаться. И для этого в классе определен метод Move
, который эмулирует перемещение.
Но главное отличие абстрактных классов от обычных состоит в том, что мы НЕ можем использовать конструктор абстрактного класса для создания экземпляра класса. Например, следующим образом:
Тем не менее абстрактные классы полезны для описания некоторого общего функционала, который могут наследовать и использовать производные классы:
В данном случае от класса Transport
наследуются три класса, которые представляют различные типы транспортных средств. Тем не менее они имеют общую черту – они могут перемещаться с помощью метода Move()
.
Мы не можем использовать конструктор абстрактного класса для создания экземпляра этого класса. Тем не менее такой класс также может определять конструкторы:
В данном случае в абстрактном классе Transport
определен конструктор – с помощью параметра он устанавливает значение свойства Name
, которое хранит название транспортного средства. И в этом случае производные классы должны в своих конструкторах вызвать этот конструктор.
Абстрактные члены классов
Кроме обычных свойств и методов, абстрактный класс может иметь абстрактные члены классов, которые определяются с помощью ключевого слова abstract
и не имеют никакого функционала. В частности, абстрактными могут быть:
- Методы.
- Свойства.
- Индексаторы.
- События.
Абстрактные члены классов не должны иметь модификатор private
. При этом производный класс обязан переопределить и реализовать все абстрактные методы и свойства, которые имеются в базовом абстрактном классе. При переопределении в производном классе такой метод или свойство также объявляются с модификатором override
(как и при обычном переопределении виртуальных методов и свойств). Также следует учесть, что если класс имеет хотя бы один абстрактный метод (или абстрактные свойство, индексатор, событие), то этот класс должен быть определен как абстрактный.
Абстрактные члены так же, как и виртуальные, являются частью полиморфного интерфейса. Но если в случае с виртуальными методами мы говорим, что класс-наследник наследует реализацию, то в случае с абстрактными методами наследуется интерфейс, представленный этими абстрактными методами.
Абстрактные методы
В примере с транспортными средствами метод Move
описывает передвижение транспортного средства. Однако различные типы транспорта перемещаются по-разному – едут по земле, летят по воздуху, плывут по воде и т. д. В этом случае мы можем сделать метод Move
абстрактным, а его реализацию переложить на производные классы:
Абстрактные свойства
Следует отметить использование абстрактных свойств. Их определение похоже на определение автосвойств. Например:
В классе Transport
определено абстрактное свойство Speed
, которое должно хранить скорость транспортного средства. Оно похоже на автосвойство, но это не автосвойство. Так как данное свойство не должно иметь реализацию, то оно имеет только пустые блоки get
и set
. В производных классах мы можем переопределить это свойство, сделав его полноценным свойством (как в классе Ship
), либо же сделав его автоматическим (как в классе Aircraft
).
Отказ от реализации абстрактных членов
Производный класс обязан реализовать все абстрактные члены базового класса. Однако мы можем отказаться от реализации, но в этом случае производный класс также должен быть определен как абстрактный:
Пример абстрактного класса
Примером является система геометрических фигур. В реальности не существует геометрической фигуры как таковой. Есть круг, прямоугольник, квадрат, но просто фигуры нет. Однако же и круг, и прямоугольник имеют что-то общее и являются фигурами: