5

一部のクラス間の関係の実装に問題があります。私は、3 つの異なるフォームを提供する 3 つの異なるクラスを取得しました。これらのクラスはすべて同じ言語を話すため、 という同じクラスから継承されTAncestorServerます。TForm1Serverその子孫を 、TForm2Server、 と呼びましょうTForm3ServerTAncestorServerと呼ばれる抽象メソッドが含まれているFunction1ためTForm1TForm2TForm3から継承された独自のクラスを介して問題なく呼び出すことができ、 という名前のプロパティを介してクラスにアクセスできますServer。しかし、問題はTForm4!と呼ばれる別の形式に関するものです。他のフォームと非常に似ていますが、それらのように独立していません。TForm2Serverまたはで動作しTForm3Serverます。それでも問題はありませんが、Function2which が宣言されているTForm2Serverような別のメソッドを想像してみてくださいTForm3ServerTForm4それらを呼び出す必要があります。私はこのように行くことができます:

if Server is TForm2Server then
   TForm2Server(Server).Function2
else if Server is TForm3Server then
  TForm3Server(Server).Function2;

しかし、それは無限の if-else 句になる可能性があります! したがって、多重継承のようなものがここで役立つかもしれないと思いました。IForm4Serverを含むというインターフェイスを宣言しましたFunction2。したがってTForm2Server、 との両方からTForm3Server継承します。私はこのようなものがうまくいくと思った:TAncestorServerIForm4Server

If Server is IForm4Server then
  IForm4Server(Server).Function2;

しかし、コンパイラはそうではないと考えています。 TAncestorServeris notIForm4Serverであるため、有効な型キャストではないと言います。これは絶対に正しいです。TForm1Server実装について何も考えておらずFunction2、空白のままにしておく必要があります。は膨大な数のメソッドとプロパティを表すため、TForm4.Server同様に宣言することはできませんが、への型キャストはまだできません。IForm4ServerFunction1IForm4ServerTAncestorServer

TForm4解決策として、2 つの異なるプロパティを同様GeneralServer: TAncestorServerに定義して、同じインスタンスまたはそれらForm4Server: IForm4Serverに割り当てることができますが、私はそれについて気分が良くありません。どうすればいいですか?そのための標準パターンはありますか?TForm2ServerTForm3Server

4

1 に答える 1

6

1 つまたは複数のインターフェイスを実装するのが正しいアプローチですが、適切な構文について少し混乱しており、インターフェイスの経験がないようです。

基本的なことは次のとおりです。

  • 任意の数のクラスに共通の祖先クラス (またはフォーム) があります。祖先は、クラスが何らかの方法で特殊化する仮想メソッドを宣言します。
  • 任意の数のメソッドを使用してインターフェイスを宣言します。インターフェイスに GUID を追加することを忘れないでください。
  • フォーム宣言を拡張して、宣言されたインターフェイスを実装し、インターフェイスをクラス宣言に追加し、宣言されたメソッドを追加します。
  • 次のことができるようになりました。
    • 祖先クラスを使用して任意の仮想メソッドをポリモーフィックに呼び出す
    • インターフェイスを実装しているかどうかを任意のフォームに問い合わせ、実装している場合は、それへのインターフェイス参照を取得し、任意のインターフェイス メソッドを呼び出します。これはすべてsupports関数を使用して行うことができます。

フォームの視覚的な継承と単純なインターフェイスを使用して、考えられる最も単純な例を作成しました。例の抜粋は次のとおりです。

共通の祖先クラス:

type
  TServerForm = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
    procedure Method1; virtual;
  end;

インターフェース:

type
  IMyInterface = interface
  ['{B7102C7E-F7F6-492A-982A-4C55CB1065B7}']
    procedure Method2;
  end;

子フォーム:

これは TServerForm から継承し、インターフェースを実装します

type
  TServerForm3 = class(TServerForm, IMyInterface)
  public
    procedure Method1; override;
    procedure Method2;
  end;

これは TServerForm から継承するだけです

type
  TServerForm4 = class(TServerForm)
  public
    procedure Method1; override;
  end;

これは TForm から直接継承し、インターフェースを実装します

type
  TNoServerForm = class(TForm, IMyInterface)
  public
    procedure Method2;
  end;

OnClickすべてのフォームは自動作成され、別のフォーム (アプリケーション例のメイン フォーム) のいくつかのボタンでメソッドを呼び出すこのコードがあります。

ポリモーフィズムに基づいて仮想メソッドを呼び出すには:

procedure TForm6.Button1Click(Sender: TObject);
var
  I: Integer;
begin
  for I := 0 to Screen.FormCount - 1 do
  begin
    if (Screen.Forms[I] is TServerForm) then
      TServerForm(Screen.Forms[I]).Method1;
  end;
end;

インターフェイスの実装に基づいてメソッドを呼び出すには:

procedure TForm6.Button2Click(Sender: TObject);
var
  I: Integer;
  Intf: IMyInterface;
begin
  for I := 0 to Screen.FormCount - 1 do
  begin
    if Supports(Screen.Forms[I], IMyInterface, Intf) then
      Intf.Method2;
  end;
end;

メソッドはメッセージを表示するだけで、すべて正常に動作します。

procedure TServerForm3.Method2;
begin
  ShowMessage(ClassName + '.Method2');
end;
于 2013-02-20T22:51:19.113 に答える