2009-07-15 3 views
1

Если у меня есть дочерний класс, дочерний класс наследует все методы от родителя, но как использовать функции из дочернего класса в родительском классе? Это абстракция? Как это сделать?Абстракция в Delphi

Мой код:

type 
cParent = class(TObject) 
private 
    function ParentFunction:byte; 
    function ChildFunction:byte;virtual;abstract; 
end; 

type 
cChild = class(cParent) 
private function ChildFunction:byte;override; 
end; 

function cChild.ChildFunction:byte; 
begin 
    Exit(20); 
end; 

function cParent.ParentFunction:byte; 
begin 
    Exit(10); 
end; 

var 
c:cParent; 

begin 
    c:= cParent.Create; 
    WriteLn(c.ChildFunction); 
    Readln; 
end. 

Он компилирует файл, но я получаю исключение абстракций.

+0

Когда вы говорите, что он компилируется хорошо, вы действительно имеете в виду, что вы * не * получили предупреждение от компилятора, говорящее вам, что вы создаете абстрактный класс? Вам нужно быть более внимательными к тому, чтобы отпечатывать подсказки и предупреждения компилятора, а не только ошибки. –

+0

Всего несколько комментариев относительно обычного стиля. Обычно в Delphi используется префикс имени класса (и другого типа) с помощью T, а не c. Возвращаемое значение функций обычно устанавливается путем установки неявной переменной Result в значение, а не с использованием Exit i.e. Результат: = 10 ;, а не Exit (10) ;. Синтаксис Exit был добавлен только в D2009 Примечание: вы также можете использовать имя функции, а не результат (ParentFunction: = 10;) - эффект тот же, и это оригинальный синтаксис Pascal –

ответ

5
c:= cParent.Create; 
WriteLn(c.ChildFunction); 

Вы создаете экземпляр класса cParent здесь. Этот класс содержит только абстрактную ChildFunction, которая может быть переопределена другими классами. Функция не реализована в cParent, поэтому вы получаете абстрактную ошибку.

Код работает, если вы используете класс cChild вместо этого, где ChildFunction реализуется:

c:= cChild.Create; 
WriteLn(c.ChildFunction); 

Для пояснения, представьте себе родительский класс с именем GeometricObject с виртуальным абстрактным методом CalculateVolume. Теперь вы можете создавать дочерние классы, такие как SphereObject или BoxObject, которые реализуют CalculateVolume, используя формулу для сфер/боксов. Но не имеет смысла создавать экземпляр GeometricObject и звонить CalculateVolume.

+0

Хорошо, но тогда что такое использование «виртуального», «абстрактного» и «переопределяющего» ключевого слова? –

+2

«virtual» означает, что метод может быть переопределен дочерними классами. «abstract» означает, что метод не реализуется родительским классом, но может быть реализован в дочерних классах. «override», ну, переопределяет виртуальные методы из родительских классов. Все абстрактные методы должны быть виртуальными, но методы могут быть виртуальными, не будучи абстрактными. – schnaader

+0

абстрактные методы - это то, что C++ называют «чистыми виртуальными» методами. Они должны быть реализованы в дочернем классе. –

1

Создание экземпляра с помощью класса ребенок:

c:= cChild.Create; 
2

Вы создаете экземпляр класса cParent. У этого класса нет реализации childFunction. c должен быть экземпляром класса cChild. Исправить код: c: = cChild.Create; WriteLn (c.ChildFunction);

0

Мне кажется, что вы путаете отношения наследования и притяжательные отношения. Если вы определяете класс «cChild» как унаследованный от класса «cParent», то класс «cChild» равен «cParent», это не значит, что класс «Родитель» имеет доступ к любым дочерним классам. Единственный способ вызывать абстрактную функцию «ChildFunction» в классе «cParent» - это другая функция, например. «ParentFunction», но только если сам объект не является «cParent»:

function cParent.ParentFunction:byte; 
begin 
    Result := ChildFunction * 2; 
end; 

var 
    c:cParent; 

begin 
    c:= cChild.Create; 
    WriteLn(c.ParentFunction); 
    Readln; 
end. 

Здесь, так как с является cChild, ParentFunction правильно называет ChildFunction, который определен в cChild.

0

В ответ на schnaader, о CS 101:

"виртуальный" означает, что метод может быть переопределен в дочерних классах.

Не только эти, но и не виртуальные функции могут быть переопределены дочерними классами. Разница очень важна: когда виртуальная функция вызывается родительским классом, функция CHILD будет выполнена. Это позволяет дочерним классам реализовывать функции, которые будут вызываться родительскими классами без родителя, когда-либо знающего о них. В этом суть полиморфизма .

Смежные вопросы