4

非常によく似たハードウェアの2つのバージョンを対象とするソフトウェアを作成していますが、APIを使用してハードウェアを初期化するまで、どのタイプが返されるかわかりません。

ハードウェアは非常に似ているため、いくつかの抽象メソッド(ハードウェアが異なる場合)を持つ親クラス(TParent)と、ハードウェアに依存する方法でそれらのメソッドを実装する2つの子クラス(TChildA、TChildB)を計画しました。

したがって、最初にTParentのオブジェクトをインスタンス化して、それがどの種類であるかを確認してから、正しい子にキャストします。

ただし、これを実行して、子クラスに完全に実装されている抽象メソッドの1つを呼び出すと、EAbstractErrorが発生します。

例えば:

myHardware:=TParent.Create();

if myHardware.TypeA then
   myHardware:=TChildA(myHardware)
else
   myHardware:=TChildB(myHardware);

myHardware.SomeMehtod();

親クラスを子クラスにキャストすることはできないと思います。また、これを行うにはおそらくもっと良い方法があると思います。ポインタはありますか?

4

3 に答える 3

5

使用しているハードウェアのタイプに応じて正しいクラスを返すファクトリ メソッドが必要です...

function CreateHardware(isTypeA: Boolean): TParent;
begin
  if IsTypeA then Result := TChildA.Create
  else Result := TChildB.Create;
end;
...

var
  myHardware: TParent;
begin
  myHardware := CreateHardware(True);
  myHardwarde.SomeMethod;
end;

... またはState パターンを使用することもできます。

どちらのアプローチにも共通するのは、TParent クラスがハードウェアのタイプを判別する知識を持っていないことです。その知識は、ファクトリ メソッド、ファクトリ メソッドの呼び出し元、ファクトリ自体、または状態クラスに転送されます。

于 2009-03-25T13:23:45.247 に答える
4

この場合、私を正しい方向に向けてくれたBinaryWorrierとMghieに感謝します。ハードウェアの初期化を最小限に抑えることが問題にならない場合は、Lievenの回答がより簡単な方法になります。

pImplイディオムは、SOの他の場所で説明されています

これが私が疑似デルファイコードでの実装をどのように理解するかです(私はこれについて公的/私的区別を気にしなかったことに注意してください):

class TParent 
  procedure SomeMethod(); abstract;
end;

class TChildA (TParent)
  procedure SomeMethod(); override;
end;

class TChildB (TParent)
  procedure SomeMethod(); override;
end;

class THardware
 HardwareSpecficMethods: TParent;
 procedure SomeMethod;
 constructor Create();

contrsuctor THardware.Create();
begin
 InitializeHardware();
 If Hardware.TypeA then
  HardwareSpecificMethods:=TChildA.Create()
 else
  HardwareSpecificMethods:=TChildB.Create();
end;

procedure THardware.SomeMethod();
begin
  HardwareSpecificMethods.SomeMethod();
end;
end; {class THardware}
于 2009-03-25T15:42:37.017 に答える
3

そうです、基本クラスから派生クラスにキャストすることはできませんし、キャストすべきではありません。

ChildオブジェクトにParentコンストラクターを再実行させたくないと思いますか?

もしそうなら 。。。

現状の親子関係を削除すると、ハードウェアクラスは1つだけになります。特定のChildAおよびChildB機能については、新しい継承パターンを作成して、ISpecificHardwareTasksインターフェイスまたは基本クラスと2つの派生クラス(SpecificAおよびSpecificB)を作成します。

ハードウェアが自己を構築しているときに、ハードウェアがどのタイプのハードウェアを使用しているかがわかるようになると、SpecificAまたはSpecificBのインスタンスが作成されます。このインスタンスはハードウェア専用です。

ハードウェアは、ISpecificHardWareTasksメソッドをラップするメソッドを公開します(それが理にかなっている場合は、そのインターフェイスを実装することもできます)。

必要に応じて、特定のクラスはハードウェアクラスへの参照を取得できます(コンストラクターでこのポインターにアクセスできるかどうかはわかりませんが、Delphiが錆びてきています)

これらのとりとめのないものがいくらか役に立ったことを願っています。

于 2009-03-25T13:32:12.790 に答える