用途によって元クラスの変更をするには?

解決


初心  2009-01-07 00:50:45  No: 33034

いつも拝見させて勉強させてもらっています。

環境はDelphi2007,WindowsXPです。

Aクラス(TOleControl)とBクラス(TOleControl)は
どちらもほぼ同様のプロパティ等を保持しているのが前提です。
プログラム内部でCの変数に対して各用途で使い分けを
していきたいのですが、その方法がわかりません。

CにAクラス、又はBクラスを代入する方法を
教えてください。

下記のようにやりたいのですが、コンパイルエラーがでます。

var
  TESTA : A;
  TESTB : B;
  C     : OleVariant;
begin

  //TESTA Create
  TESTA := A.Create(TESTA);
  //TESTB Create
  TESTB := B.Create(TESTB);

  if(xxx) then 
     c := TESTA; 
  end
  else begin
     c := TESTB; 
  end; 

  //Cのプロパティ参照
  C.xxxx;


monaa  2009-01-07 03:58:52  No: 33035

詳しくないので聞き流してください、
多分、クラス設計の概念から行くとこの設計は無理だと思います。
親はあくまで一つじゃなかったでしたっけ?


初心  2009-01-07 18:21:31  No: 33036

monaaさん、回答ありがとうございます。

こちらでも色々試してみてますが、
出来そうで出来ないもどかしい状態です。

すみませんが、引き続きよろしくお願い致します。


take  2009-01-07 21:08:34  No: 33037

クラスAとBは親は同じで用途は違うけど同一に扱いたいということ?
こちらのイメージでは印刷と印刷プレビューみたいにプロパティは同じだけど動作が違うのを期待しているのでしたら

フォームにボタンとチェックボックス1つ置いて組んでみました。
書き込み内容をそのまま使おうとすると至る所でエラー出ますけど
それが原因とか言うことは無いですよね?

type
  A = class(TOleControl)
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

type
  B = class(TOleControl)
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

type
  TForm1 = class(TForm)
    Button1: TButton;
    CheckBox1: TCheckBox;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
  TESTA : A;
  TESTB : B;
  C     : TOleControl;
begin

  //TESTA Create
  TESTA := A.Create(Self);
  //TESTB Create
  TESTB := B.Create(Self);

  if(CheckBox1.Checked) then
    c := TESTA
  else begin
     c := TESTB;
  end;

  //Cのプロパティ参照
  C.Align := alClient;
end;


KHE00221  2009-01-08 05:43:41  No: 33038

こうじゃないか?

  TO1 = class(TWebBrowser)
  private
    FA: Integer;
  published
    property A:Integer read FA write FA;
  end;

  TO2 = class(TWebBrowser)
  private
    FB: Integer;
  published
    property B:Integer read FB write FB;
  end;

procedure TForm9.Button1Click(Sender: TObject);
var
    O1 : TO1;
    O2 : TO2;
    O : TOleControl;
begin
    O1 := TO1.Create(Self);
    O2 := TO2.Create(Self);
    if CheckBox1.Checked = True then O := O1 else O := O2;
    O.Align := alClient;
    O2.Free;
    O1.Free;
end;


ttt  2009-01-08 09:26:23  No: 33039

それだとFAとFBの使いどころが……
状況としてはこういうことをやりたいんですかね?

type
  A = class(TOleControl)
    property x: Integer;
    // その他のAの実装
  end;
  B = class(TOleControl)
    property x: Integer;
    // その他のBの実装
  end;
...
  var C: TOleControl;
...
  if xxx then C := TESTA else C := TESTB;
  ShowMessage(IntToString(C.x)); // NG

もちろんこれは無理です。(TOleControlはxを持っていないし、
A.xとB.xはたまたま名前が同じだけで無関係なプロパティですから。)
A, Bとも自作のクラスなら共通の親クラスを作ってやればいいのでは。

type
  TABParent = class(TOleControl)
    property x: Integer;
    // その他のA,B共通の実装
  end;

  A = class(TABParent)
    // A固有の実装
  end;
  B = class(TABParent)
    // B固有の実装
  end;
...
  var P: TABParent;
...
  if xxx then P := TESTA else P := TESTB;
  ShowMessage(IntToString(P.x)); // OK

xは完全に共通ではなくてAとBで異なる動作をさせたいということなら、
仮想化してそれぞれのクラスでオーバーライドしてやればいいですね。

A,B,xが具体的に何なのかわかりませんが、仮に自作でないとしても
クラス構造をさかのぼっていったら共通の親クラスがいないでしょうか?


初心  2009-01-08 18:45:26  No: 33040

tttさんの言うとおり共通の親クラスを定義して
行うことにしました。

monaaさん、takeさん、KHE00221さん、tttさん
本当にありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加