Технологии программирования
Шрифт:
Динамические методы вызываются медленнее, но позволяют более экономно расходовать память. Каждому динамическому методу системой присваивается уникальный индекс. В таблице динамических методов (Dynamic Method Table, DMT) класса хранятся индексы и адреса только тех динамических методов, которые описаны в данном классе (базовая информация по обработке динамических методов содержится в модуле x: \delphi\source\rtl\sys\dmth.asm). При вызове динамического метода происходит поиск в этой таблице. В случае неудачи просматриваются все классы-предки в порядке иерархии и, наконец, TObject, где имеется стандартный обработчик вызова динамических
Для перекрытия и виртуальных, и динамических методов служит новая директива override, с помощью которой (и только с ней!) можно переопределять оба этих типа методов:
Первый из методов в примере создается заново, остальные два — перекрываются. Попытка применить override к статическому методу вызовет ошибку компиляции.
В Object Pascal абстрактными называются методы, которые определены в классе, но не содержат никаких действий, никогда не вызываются и должны быть переопределены в потомках класса. Абстрактными могут быть только виртуальные и динамические методы. Для этого используется директива abstract, указываемая при описании метода:
При этом никакого кода для этого метода писать не нужно. Как и ранее, вызов метода NeverCallMe приведет к ошибке времени выполнения.
7. ПОЛИМОРФИЗМ
Рассмотрим пример, которой поясняет, для чего нужно использование абстрактных методов. Пусть у нас имеются некое обобщенное поле для хранения данных — класс TField и три его потомка — для хранения строк, целых и вещественных чисел. В данном случае класс Tfield не используется сам по себе; его основное предназначение — быть родоначальником иерархии конкретных классов — "полей" и дать возможность абстрагироваться от частностей. Хотя параметр у ShowData и описан как TField, но если поместить туда объект этого класса, произойдет ошибка вызова абстрактного метода:
В
Правила контроля соответствия типов (typecasting) языка Pascal говорят о том, что объекту как указателю на экземпляр объектного типа может быть присвоен адрес любого экземпляра любого из дочерних типов. В процедуре ShowData параметр описан как TField. Это значит, что в нее можно передавать объекты классов и TStringField, и TIntegerField, и TExtendedField, и любого другого потомка TField.
Но какой (точнее, чей) метод GetData при этом будет вызван? Тот, который соответствует классу фактически переданного объекта. Этот принцип называется полиморфизмом, и он, пожалуй, представляет собой наиболее важный "козырь" ООП. Допустим, имеется дело с некоторой совокупностью явлений или процессов. Чтобы смоделировать их средствами ООП, нужно выделить их самые общие, типовые черты. Те из них, которые не изменяют своего содержания, должны быть реализованы в виде статических методов. Те же, которые варьируют при переходе от общего к частному, лучше облечь в форму виртуальных методов. Основные "родовые" черты (методы) нужно описать в классе-предке и затем перекрыть их в классах-потомках. В предыдущем примере программисту, пишущему процедуру вроде ShowData, важно лишь одно: то, что любой объект, переданный в нее, является потомком TField, и он умеет сообщить о значении своих данных (выполнив метод GetData).