以前ここで質問させて頂いたものです。D5Proを使用しています。
いちおうヘルプのinheritedの使い方は呼んでみたのですが、
イマイチどのように動作しているかが解らない状態です。
ボタンとフォームなどを使って、動作を簡単に追えるような
サンプルなど提示してもらえないでしょうか?
また、これに関する解説ページをご存知の方がいらっしゃったら
教えて教えて頂けないでしょうか?
宜しくお願い致します。
最小化・最大化を検知する例です。
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;
レス有難う御座います。
ちょっとやってみます。。。
継承もとのメソッドとか呼び出すってことじゃないんですか?
inherited Create;
で継承元クラスのCreateが呼ばれるとかだと思いますが。
クラスの型宣言と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;
#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.
がびょうさん
overrideとoverloadのテスツさん
Delphi foreverさん
レス有難う御座います!遅レスで申し訳ありません…
ご提示頂いたサンプルコードを実行しながら追ってみて、
なんとな〜〜くではありますが、何とか解ってきた気がします!
先日、古本屋さんで「Borland Delphi5 オフィシャルコースウェア 応用編」を購入したので、これを熟読してもちっと理解を深めたいと思います。
ご親切に色々と有難う御座いました^^
ツイート | ![]() |