Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка ООП.doc
Скачиваний:
23
Добавлен:
08.11.2018
Размер:
1.4 Mб
Скачать
  1. Абстрактные методы

Если проанализировать рассмотренный выше пример с иерархией классов графических объектов, то можно обнаружить, что у класса TFigure имеются два виртуальных метода Draw и MouseClick, чья реализация непонятна. Неизвестно, как можно нарисовать абстрактную фигуру, и каким образом можно проанализировать попадание курсором мыши по абстрактной фигуре. С другой стороны, эти методы должны быть объявлены в этом классе, поскольку они имеются у всех потомков, и предполагается их вызов через указатель на TFigure. Для классов-потомков, таких как круг, эллипс, прямоугольник известно, в отличие от фигуры, как их рисовать и как анализировать положение курсора. Действия для разных фигур различаются, поэтому используется виртуальное или динамическое перекрытие. Таким образом, есть методы, которые обязательно должны быть объявлены в классе-предке и объявлены как виртуальные или динамические, чтобы потомки могли их перекрывать. Но писать реализацию для этих методов бессмысленно. Такие методы объявляют как абстрактные.

Абстрактными называются виртуальные и динамические методы, которые определены в классе, но не содержат никаких действий, никогда не вызываются и обязательно должны быть перекрыты в потомках класса. Абстрактными могут быть только виртуальные и динамические методы. В Object Pascal для объявления метода абстрактным, при его описании используется директива abstract после директивы virtual или dynamic:

TSampleObject = class Procedure X; virtual; abstract; ... end;

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

Например, описание класса TFigure из предыдущего примера будет выглядеть следующим образом:

interface type TFigure = class procedure Draw; virtual; abstract; //рисование function MouseClick(x,y: integer): boolean; virtual; abstract; //анализ щелчка мышью ... end;

Реализация этих методов для TFigure не нужна.

Работать с иерархией графических объектов можно будет в точности так же, как раньше.

Procedure Test; var Figure: array[1..100] of TFigure; begin Figure[0] := TCircle.Create(10,10,3); Figure[1] := TEllipse.Create(20,10,3,5); Figure[2] := TSquare.Create(30,20,10); Figure[3] := TRectangle.Create(50,50,60,70); ... for i := 1 to 100 do if Figure[i]<>nil then Figure[i].Draw; //Будет вызываться метод Draw соответствующего //класса-потомка ... for i := 1 to 100 do Figure[i].Free; end;

При выполнении процедуры Test ошибки не произойдет, если только в массиве Figure не будет не одного объекта класса TFigure. Будут вызываться методы Draw классов-потомков, для которых определена реализация. Если же будет создан объект класса TFigure, то произойдет попытка вызвать абстрактный метод Draw, реализация для которого не определена, что вызовет ошибку. Поэтому, как правило, объекты классов, имеющих абстрактные методы, не создаются.

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

    1. Абстрактные классы в C++

Если виртуальная функция базового класса не имеет реализации, ее можно объявить «чистой виртуальной функцией». Для этого функция объявляется с ключевым словом virtual и при объявлении она устанавливается в ноль:

class CBase { public: virtual int funct1(void) = 0;//чистая виртуальная функция virtual int funct2(void);    //объявление обычной //виртуальной функции ... };

Чистая виртуальная функция не должна иметь реализации.

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