inheriteの使い方は?

解決


ぽぽろん  2006-03-07 01:22:57  No: 20370

以前ここで質問させて頂いたものです。D5Proを使用しています。

いちおうヘルプのinheritedの使い方は呼んでみたのですが、
イマイチどのように動作しているかが解らない状態です。

ボタンとフォームなどを使って、動作を簡単に追えるような
サンプルなど提示してもらえないでしょうか?

また、これに関する解説ページをご存知の方がいらっしゃったら
教えて教えて頂けないでしょうか?

宜しくお願い致します。


deldel  2006-03-07 01:32:20  No: 20371

最小化・最大化を検知する例です。

Private 宣言
procedure WM_SYSCOMMAND(var Msg: TWMSYSCOMMAND); message WM_SYSCOMMAND;

procedure TForm1.WM_SYSCOMMAND(var Msg: TWMSYSCOMMAND);
begin
  //パターン1(変化する前にメッセージ表示)
  if Msg.CmdType = SC_MINIMIZE then
    ShowMessage('最小化します')
  else if Msg.CmdType = SC_MAXIMIZE then
    ShowMessage('最大化します');

  inherited; //最後にこれ!!
{

  //パターン2(変化してからメッセージ表示)
  inherited; //最初にこれ!!

  if Msg.CmdType = SC_MINIMIZE then
    ShowMessage('最小化しました')
  else if Msg.CmdType = SC_MAXIMIZE then
    ShowMessage('最大化しました');
}
end;


ぽぽろん  2006-03-07 02:01:29  No: 20372

レス有難う御座います。
ちょっとやってみます。。。


がびょう  URL  2006-03-08 21:31:25  No: 20373

継承もとのメソッドとか呼び出すってことじゃないんですか?

inherited Create;
で継承元クラスのCreateが呼ばれるとかだと思いますが。


overrideとoverloadのテス  2006-03-08 23:24:46  No: 20374

クラスの型宣言とoverride, overload されたメソッドの動作の違いがわかる・・・かも。

type
  {A___}
  TClassA =class
    Data: Integer;
    constructor Create; virtual;
    function HogeHoge:Integer; virtual;
    function GClass(aDClass: TClassA): String;
  end;
  {B___}
  TClassB =class(TClassA)
    constructor Create; override;
    function HogeHoge:Integer; override;
    function GClass(aDClass: TClassB): String; overload;
  end;
  {C___}
  TClassC =class(TClassB)
    function HogeHoge:Integer; override;
    function GClass(aDClass:TClassC): String; overload;
  end;
  {D___}
  TClassD =class(TClassB)
    function HogeHoge:Integer; override;
  end;

  THogeForm = class(TForm)
    ListBox1: TListBox;
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    ClassA1 :TClassA;
    ClassB1 :TClassB;
    ClassC1 :TClassC;
    ClassD1 :TClassD;

    ClassA2,
    ClassB2,
    ClassC2,
    ClassD2 :TClassA;
  public
    { Public 宣言 }
  end;

implementation

{A___}
constructor TClassA.Create;
begin
  inherited Create;
  Data := 1;
end;
function TClassA.HogeHoge:Integer;
begin
  Result := Data;
end;
function TClassA.GClass(aDClass: TClassA): String;
begin
  Result := 'ClassA1';
end;

{B___}
constructor TClassB.Create;
begin
  inherited Create;
  Data := 2;
end;
function TClassB.HogeHoge:Integer;
begin
  Result := inherited HogeHoge;
  Result := Result + 10;
end;
function TClassB.GClass(aDClass: TClassB): String;
begin
  Result := 'ClassB1';
end;

{C___}
function TClassC.HogeHoge:Integer;
begin
  Result := Data * 2;
end;
function TClassC.GClass(aDClass: TClassC): String;
begin
  Result := 'ClassC1';
end;

{D___}
function TClassD.HogeHoge:Integer;
begin
  Result := inherited HogeHoge;
  Result := Result + 1000;
end;

procedure THogeForm.FormCreate(Sender: TObject);
begin
  ClassA1 := TClassA.Create;
  ClassB1 := TClassB.Create;
  ClassC1 := TClassC.Create;
  ClassD1 := TClassD.Create;

  ClassA2 := TClassA.Create;
  ClassB2 := TClassB.Create;
  ClassC2 := TClassC.Create;
  ClassD2 := TClassD.Create;
end;

procedure THogeForm.FormDestroy(Sender: TObject);
begin
  ClassA1.Free;
  ClassB1.Free;
  ClassC1.Free;
  ClassD1.Free;
  ClassA2.Free;
  ClassB2.Free;
  ClassC2.Free;
  ClassD2.Free;
end;

procedure THogeForm.Button1Click(Sender: TObject);
begin
  ListBox1.Items.Clear;
  with ListBox1.Items do begin
    Add('A1: ' + Format('%5d', [ClassA1.HogeHoge]));
    Add('B1: ' + Format('%5d', [ClassB1.HogeHoge]));
    Add('C1: ' + Format('%5d', [ClassC1.HogeHoge]));
    Add('D1: ' + Format('%5d', [ClassD1.HogeHoge]));
    Add('A2: ' + Format('%5d', [ClassA2.HogeHoge]));
    Add('B2: ' + Format('%5d', [ClassB2.HogeHoge]));
    Add('C2: ' + Format('%5d', [ClassC2.HogeHoge]));
    Add('D2: ' + Format('%5d', [ClassD2.HogeHoge]));
  end;
end;

procedure THogeForm.Button2Click(Sender: TObject);
begin
  ListBox1.Items.Clear;
  with ListBox1.Items do begin
    {A}
    Add('A1-A1: ' + ClassA1.GClass(ClassA1));
    Add('A1-B1: ' + ClassA1.GClass(ClassB1));
    Add('A1-C1: ' + ClassA1.GClass(ClassC1));
    Add('A1-D1: ' + ClassA1.GClass(ClassD1));
    {B}
    Add('B1-A1: ' + ClassB1.GClass(ClassA1));
    Add('B1-B1: ' + ClassB1.GClass(ClassB1));
    Add('B1-C1: ' + ClassB1.GClass(ClassC1));
    Add('B1-D1: ' + ClassB1.GClass(ClassD1));
    {C}
    Add('C1-A1: ' + ClassC1.GClass(ClassA1));
    Add('C1-B1: ' + ClassC1.GClass(ClassB1));
    Add('C1-C1: ' + ClassC1.GClass(ClassC1));
    Add('C1-D1: ' + ClassC1.GClass(ClassD1));
    {D}
    Add('D1-A1: ' + ClassD1.GClass(ClassA1));
    Add('D1-B1: ' + ClassD1.GClass(ClassB1));
    Add('D1-C1: ' + ClassD1.GClass(ClassC1));
    Add('D1-D1: ' + ClassD1.GClass(ClassD1));

    {A}
    Add('A2-A2: ' + ClassA2.GClass(ClassA2));
    Add('A2-B2: ' + ClassA2.GClass(ClassB2));
    Add('A2-C2: ' + ClassA2.GClass(ClassC2));
    Add('A2-D2: ' + ClassA2.GClass(ClassD2));
    {B}
    Add('B2-A2: ' + ClassB2.GClass(ClassA2));
    Add('B2-B2: ' + ClassB2.GClass(ClassB2));
    Add('B2-C2: ' + ClassB2.GClass(ClassC2));
    Add('B2-D2: ' + ClassB2.GClass(ClassD2));
    {C}
    Add('C2-A2: ' + ClassC2.GClass(ClassA2));
    Add('C2-B2: ' + ClassC2.GClass(ClassB2));
    Add('C2-C2: ' + ClassC2.GClass(ClassC2));
    Add('C2-D2: ' + ClassC2.GClass(ClassD2));
    {D}
    Add('D2-A2: ' + ClassD2.GClass(ClassA2));
    Add('D2-B2: ' + ClassD2.GClass(ClassB2));
    Add('D2-C2: ' + ClassD2.GClass(ClassC2));
    Add('D2-D2: ' + ClassD2.GClass(ClassD2));
  end;
end;


Delphi forever  2006-03-25 13:42:23  No: 20375

#inherited
    
    inherited は、ご先祖様のメソッドやプロパティにアクセスするだけです。

    これ以外の何者でもありません。理解に苦しんでいるなら、
    この言葉そのままの意味で受け取ってください。

    忘れ去られがちですが 異なる名前のメンバーにもアクセスできます。
      type 
        TClassB=class(TClassA)
           procedure ProcA; override;
        end;

      procedure TClassB.ProcB;
      begin
        inherited ProcA;
      end;

    いっぱいあったって別にかまいません。
      procedure TClassB.ProcB;
      begin
        inherited ProcA;
        inherited ProcB;
        inherited ProcC('hoe',1,2);
      end;

    他にも

    returnも返せます。
      Result:= inherited Something;

    代入もできます。
      inherited Test:=ABC;

    論理式中にも使えます。
      if (not (inherited Enabled)) and (inherited Text='') then 
          Raise Exception.Create('hoe');

    よくみる
    inherited;
    なるシンプルな記述は、
    それが記述してある関数または手続きと同じ名前、パラメータで呼び出すという事です。
  

#override
  inheritedを語るには、overrideも語らなくてはなりません…。

  override したメソッドは 新しく実装した部分が、そのクラスにのみ影響する
  のではなく、上位クラス(TObject方面)が、そのメソッドを内部で呼び出している
  場合にも、影響します。 (ご先祖様にも影響するということです。)

  overrideしていなくても、inheritedは、呼び出すことができます。 
  overrideしてないメソッドは、
  上位クラスからは通常、アクセスできず、上位クラスで実装されている段階の
  処理内容が実行されます。(ご先祖様は影響を受けません。)

  例えば、TButton.Click;
  などは、内部でも(ご先祖様も) Clickを呼び出しています。(マウスボタンがあがった時)

  なので、Click を override して
    uses ....StdCtrls;
    type
    TMyButton=class(TButton)

      procedure Click; override;      // O V E R R I D E
  
    end;

    implementation
    procedure TMyButton.Click;
    begin
       inherited Click;
       MessageBeep(MB_OK);
    end;
    procedure TForm1.OnCreate( Sender: TObject);
    begin
      with TMyButton.Create(Self) do
      begin
        Parent:=Self;
        //Click;                //後述で使います
        //OnClick:=ClickHandler;//後述で使います
      end;
    end;   
    procedure TForm1.ClickHandler(Sender: TObject);
    begin
        //後述で使います
        //MessageDlg('ほえ?',mtInformation,[mbOK],0);
    end;

  などとすれば、
  クリックするたびに音がなります。

  に対して

  override をつけない場合には、
  Clickを呼び出すコードを書かない限り、音はなりません。
  例えば
    procedure TForm1.OnCreate( Sender: TObject);
    begin
      with TMyButton.Create(Self) do
      begin
        Parent:=Self;
        Click;                      // この瞬間
        OnClick:=ClickHandler;
        Left:= (Self.ClientWidth - Width ) div 2;
        Top := (Self.ClientHeight- Height) div 2;
      end;
    end;
  この瞬間以外、音はなりません。
  
  ちなみに override しても inherited しないと、クリックしても
  OnClickイベントが発生しなくなります。
  
    procedure TMyButton.Click;
    begin
        // inherited Click;          // C O M M E N T   O U T 
        MessageBeep(MB_OK);
    end;
    (注: Clickをoverride してください)
  
#virtual
  上位クラスで virtualかdynamic じゃないと overrideは できません。
  
  が、前述した内容を踏まえると、再実装したいメソッドがあるならば、
  virtual じゃなくても、再実装はできるし、中で inheritedも
  使えます。
 
  (ただし、先祖には影響しないというところを忘れたまま実装を
  すすめるとバグっぽくなるので注意が必要)
  
  また、パラメータリストが違うからといって再実装をあきらめることもありません。
    上位クラスで procedure Proc(A: integer); virtual;

  となっている場合、
  
    下位クラスで procedure Proc(A,B: integer); reintroduce;
  としても
    中で inherited Proc(A) とやっていれば、期待通り動きます。

  しかし、
  前述のとおり、ご先祖様は Proc(A: integer) のまま
  アクセスしてくるので、事前にご先祖様の十分な調査が必要です。  

  dynamicとvirtualの違いはヘルプにあるとおりです。
  コーディング段階での制約などは特に違いがありません。
  ので補足も特にありません。
  
  
#overload  
  overload は全く別物です。
  派生、継承うんぬんとは関係がありません。(と思います)
  procedure Proc(A:integer); overload;    //#1
  procedure Proc(A:string);  overload;    //#2
  procedure Proc(A,B: integer); overload; //#3
  
  begin
      Proc(0);       // #1 実行
      proc('string');// #2 実行
      proc(0,1);     // #3 実行
  end;
  
  これだけのことです。
  (私的ですが、私は滅多に overload は書かないので、実際のところ
  使い勝手など不明なのですが、あまり多用すると、コーディングの時、
  型が把握できなくて、大変なのではないかと思います。
  まあ…お好みで。)

  
  
#プロパティ
  TListViewやTStatusPanels.Items など、VCLの中には
  
  property Items[index:integer]: TListItem read GetItem write SetItem;
  
  などの GetItemや SetItemが private で virtualじゃない場合が多々あります。
  が、あきらめずに、下位クラスで、このまま
  property Items[index:integer]: TMyListItem read GetItem write SetItem;
  を再定義しても、表面からたたけるメソッドやプロパティである限り、
  期待通り動きます。 
  
  privateなGetItemやSetItemにはアクセスできないので プロパティにアクセスします。

  Result:= (inherited Items[index]) as TMyListItem; 
  
  (ただし、インスタンスを作成する部分も再実装や継承などが必要、
  かつItemsも同系統の派生である必要がある)
  
  
※ 今回 with を使いましたが
   with 文は、適材適所で、手の抜けるところ意外で使うのは、お勧めしません。

こんなところで、いかがですか。
inherited の使い道…可能性が広がったでしょうか。
DelphiがDelphiであるうちに、ちょっと書いてみたくなりました。
(手遅れという気もしますが)
なお、情報の正確性は保証できません。
訂正があれば遠慮なさらず。

Delphi フォーえばーーーーーーーーーーーーー!

thanks.


ぽぽろん  2006-03-28 01:26:38  No: 20376

がびょうさん
overrideとoverloadのテスツさん
Delphi foreverさん
レス有難う御座います!遅レスで申し訳ありません…
ご提示頂いたサンプルコードを実行しながら追ってみて、
なんとな〜〜くではありますが、何とか解ってきた気がします!
先日、古本屋さんで「Borland Delphi5 オフィシャルコースウェア 応用編」を購入したので、これを熟読してもちっと理解を深めたいと思います。
ご親切に色々と有難う御座いました^^


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

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






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