Шаг 153.
Язык программирования C#. Начала
Абстрактные классы и интерфейсы. Знакомство с абстрактными классами

    На этом шаге мы приведем общие сведения об абстрактных классах и особенностях их применения.

    Есть такое понятие, как абстрактный метод. Абстрактным называется метод, который в классе только объявлен, но не описан. Под объявлением метода подразумевается ситуация, когда в теле класса указан тип результата метода, его название и приведен список аргументов (после закрывающей круглой скобки ставится точка с запятой), а тела метода нет. То есть блока из фигурных скобок с командами, выполняемыми при вызове метода, нет вообще. Но чтобы метод был абстрактным, недостаточно описать его без тела с командами. В описании метода необходимо явно указать, что метод абстрактный. Для этого используется ключевое слово abstract. Шаблон описания абстрактного метода представлен ниже:

  доступ abstract тип имя(аргументы);

    Сначала указывается спецификатор уровня доступа, затем ключевое слово abstract, после него - идентификатор типа результата метода, название и список аргументов. При этом аргументы описываются, как и в обычном (не абстрактном) методе, с указанием типа аргумента и его формального названия. В конце ставится точка с запятой.

    Если в классе есть хотя бы один абстрактный метод, то такой класс также считается абстрактным. Абстрактный класс, как и абстрактный метод, описывается с ключевым словом abstract.

    Поскольку у абстрактного метода нет тела и не известно, какие команды должны выполняться при вызове метода, то такой метод вызвать нельзя. Поэтому, как вы могли догадаться, на основе абстрактного класса нельзя создать объект. В этом случае все логично: если бы такой объект можно было создать, то у него был бы метод, который нельзя вызвать. А это, как минимум, странно и непоследовательно. Но тогда возникает вопрос: а зачем вообще нужны абстрактные классы? Ответ состоит в том, что абстрактный класс может (и должен) использоваться как базовый при наследовании. Это его главное и наиболее важное назначение - быть базовым классом. Общая схема такова: создается абстрактный класс, а затем путем наследования на основе абстрактного класса создаются обычные (не абстрактные) производные классы. При этом в производных классах абстрактные методы переопределяются: описывается полная версия метода, и, как при переопределении обычных методов, в описании указывается ключевое слово override. В производном классе должны быть переопределены (описаны) все абстрактные методы из абстрактного базового класса.


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

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

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


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

    Также следует заметить, что хотя создать объект абстрактного класса нельзя, но можно объявить объектную переменную для абстрактного класса. Эта переменная не может ссылаться на объект абстрактного класса (поскольку такой объект создать нельзя), зато она может ссылаться на объект производного класса. А поскольку абстрактные методы по умолчанию являются виртуальными и переопределяются в производном классе, то через объектную переменную базового абстрактного класса будут вызываться именно те версии методов, что определены в производном классе. Далее перейдем к рассмотрению примеров.


Абстрактными могут быть также свойства и индексаторы. При описании абстрактного свойства или индексатора используется ключевое слово abstract. В теле свойства или метода аксессоры не описываются. Указываются только ключевые слова get и set или только одно из них, если у свойства или индексатора только один аксессор.

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


    На следующем шаге мы рассмотрим использование абстрактных классов.




Предыдущий шаг Содержание Следующий шаг