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