2009-07-15 10 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を付けます。 関数の戻り値は、通常Exitを使用するのではなく、Exit(Result)= 10でなくExit(10);を使用して暗黙のResult変数を値に設定することによって設定されます。 Exit構文はD2009にのみ追加されました 注:結果(ParentFunction:= 10;)ではなく関数名を使用することもできます - エフェクトは同じで、オリジナルのパスカル構文です –

答えて

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

あなたがここにcParentクラスのインスタンスを作成します。このクラスには、ほかのクラスによってオーバーライドできる抽象的なChildFunctionのみが含まれます。この関数はcParentに実装されていないため、抽象的なエラーが発生します。

コードが動作するあなたの代わりにcChildクラスを使用する場合、どこChildFunctionが実装されています。明確にするため

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

を、仮想抽象メソッドCalculateVolumeGeometricObjectという名前の親クラスを想像してみてください。球体/ボックスの数式を使用してCalculateVolumeを実装するSphereObjectまたはBoxObjectのような子クラスを作成できるようになりました。しかし、GeometricObjectのインスタンスを作成してCalculateVolumeと呼ぶのは意味がありません。

+0

「仮想」、「抽象的な」、および「上書き」キーワードの使用? –

+2

"virtual"は、メソッドが子クラスによってオーバーライドできることを意味します。 「抽象的」とは、メソッドが親クラスによって実装されていないことを意味しますが、子クラスで実装できます。 "上書き"は、親クラスからの仮想メソッドをオーバーライドします。すべての抽象メソッドは仮想でなければなりませんが、抽象メソッドではなく仮想メソッドにすることができます。 – schnaader

+0

抽象メソッドは、C++が「純粋仮想」メソッドと呼ぶものです。子クラスで実装する必要があります。 –

1

は、子クラスを使用してインスタンスを作成します。

c:= cChild.Create; 
2

cParentクラスのインスタンスを作成します。このクラスには、childFunctionの実装はありません。 cはcChildクラスのインスタンスでなければなりません。 修正コード: c:= cChild.Create; WriteLn(c.ChildFunction);

0

あなたは相続関係と所有関係を混同しているようです。クラス "cPild"から継承されたクラス "cChild"を定義した場合、 "cChild"クラスは "cParent"であるであり、 "Parent"クラスがすべての子クラスにアクセスできるという意味ではありません。クラス "cParent"で抽象関数 "ChildFunction"を呼び出す唯一の方法は、別の関数、たとえば"ParentFunction" が、オブジェクト自体は "cParent" でない場合にのみ:ここでは

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

var 
    c:cParent; 

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

、cはcChildであるため、ParentFunctionが正しくcChildで定義されているChildFunctionを呼び出します。 CS 101についてschnaaderに対応して

0

、:

"仮想の" メソッドは、子クラスでオーバーライドすることができることを意味します。

これだけでなく、仮想以外の機能も子クラスによってうまく上書きされる可能性があります。違いは非常に重要です:仮想関数が親クラスによって呼び出されると、CHILD関数が実行されます。これにより、子クラスは、親クラスで呼び出される関数を実装することができます。これは多形の本質です。