Функционирование объектов обеспечивается различными типами методов, которые различаются особенностями реализации механизма наследования.
Абстрактными называются методы, которые определены в классе, но не содержат никаких действий, никогда не вызываются и обязательно должны быть переопределены в потомках-классах.
Абстрактными могут быть только виртуальные и динамические методы. Такие методы объявляются с помощью одноименной директивы. При этом никакого кода для реализации метода писать не нужно. Вызов абстрактного метода приведет к созданию исключительной ситуации EabstractError.
В примере класс TField не используется сам по себе. Его основное предназначение- быть родоначальником иерархии конкретных классов, и дать возможность абстрагироваться от частностей. Хотя параметр процедуры ShowData и описан как TField, но если передать в нее объект этого класса произойдет исключительная ситуация вызова абстрактного метода.
Статические методы, а так же любые поля в объектах-потомках ведут себя одинаково: можно без ограничений перекрывать старые имена и при этом изменять тип методов. Код нового статического метода полностью перекрывает код старого метода.
Type Tobj1=class
I:real;
Procedure SetData (AValue:real);
End;
Tobj2=class (Tobj1)
I:integer;
Procedure SetData (AValue:integer);
End;
Implementation
Procedure Tobj1.SetData(AValue:real);
Begin
I:=AValue;
End;
Procedure Tobj2.SetData(AValue:integer);
Begin
I:=AValue;
Inherited SetData(0,99);
End;
В этом примере методы с именем SetData присваивают значение разным полям с именем «i». Перекрытое поле предка не доступно в потомке, поэтому конечно два одноименных поля с именем «I» это абсурд, так сделано только для примера.
В отличие от поля внутри других методов, перекрытый доступен при указании зарезервированного слова «Inherited». По умолчанию все методы объектов являются статическими, то есть их адрес определяется еще на стадии компиляции проектов, поэтому они вызываются быстрее всех.
Принципиально отличаются от статических виртуальные и динамические методы. Они должны быть объявлены путем добавления соответствующей директивы Virtual, Dynamic. С точки зрения наследования методы этих двух видов одинаковы. Они могут быть перекрыты в дочернем классе только одноименными методами, имеющими тот же тип.
В рассмотренном выше примере у компилятора нет возможности определить класс объекта фактически переданного в процедуру ShowData. Нужен механизм, позволяющий определить это прямо во время выполнения. Такой механизм называется поздним связыванием. Для этого используется таблица виртуальных методов и таблица динамических методов.
Разница между виртуальными и динамическими методами заключается в особенности поиска адреса. Когда компилятор встречает обращение к виртуальному методу, он подставляет в место прямого вызова по конкретному адресу код, который обращается к таблице виртуальных методов и извлекает оттуда нужный адрес. Такая таблица есть для каждого класса. В ней хранятся адреса всех виртуальных методов класса, независимо от того унаследованы ли они от предков или перекрыты в данном классе.
Отсюда «+» и «-» виртуальных методов:
1. они вызываются сравнительно быстро, однако для хранения указателей на них в таблице виртуальных методов требуется большое количество памяти.
2. динамические методы вызываются медленнее, но позволяют более экономично расходовать память.
3. каждому динамическому методу системой присваивается уникальный индекс
4. в таблице динамических методов класса хранятся индексы и адреса только тех динамических методов, которые описаны только в этом классе.
5. при вызове динамического метода происходит поиск в этой таблице, в случае не удачи просматриваются таблицы динамических методов всех классов-предков в порядке иерархии и наконец класс Tobject, где имеется стандартный обработчик вызова динамических методов.
Для перекрытия виртуальных и динамических методов служит директива Override, с помощью которой и только с ней можно переопределить оба этих метода.