请教OOP问题,关于继承(30分)

  • 主题发起人 主题发起人 WilliamGui
  • 开始时间 开始时间
W

WilliamGui

Unregistered / Unconfirmed
GUEST, unregistred user!
写法:
TA=class
protected
procedure test
virtual;
end;
TB=class(TA)
protected
procedure test
override
//如果这里改为virtual对TC类有什么影响?
end;
TC=class(TB)
protected
procedure test
override;
end;
 
TC类将不可能访问到TA类的Test方法,除非强制转型为TA
 
事实上证明,没什么不同,不信,你试试
 
请问你的没什么不同,代码是怎么写的?
 
如果TA不包括任何代码
则TB怎么写就执行什么
如果TA.test中含有可执行代码,则TB中应该调用TA的函数否则只执行TB的操作
TC如果继承了TB的Test方法,则需要调用TB的test方法,不然TB和TA的test方法都不会执行
 
关键是对 override 关键字的理解!
 
virtual总是引入与先前继承来的同名方法无关的新的虚方法
 
type
TA=class
protected
FNum:Integer;
procedure test
virtual;
end;
TB=class(TA)
protected
procedure test
override
//@@1 如果这里改为virtual对TC类有什么影响?
end;
TC=class(TB)
protected
procedure test
override;
end;

{ TA }

procedure TA.test;
begin
Inc(FNum,1000);
end;

{ TB }

procedure TB.test;
begin
inherited;
Inc(FNum,100);
end;

{ TC }

procedure TC.test;
begin
inherited;
Inc(FNum,10);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
MyObj1:TA;
MyObj2:TB;
begin
MyObj1:=TC.Create;
MyObj2:=TC.Create;
MyObj1.test
//@@2
MyObj2.test
//@@3
ShowMessage(Format('Num1:%d Num2:%d',[MyObj1.FNum,MyObj2.FNum]));
MyObj1.Free;
MyObj2.Free;
end;

如果将@@1处改为virtual,那么TB的test方法就不再继承TA的test方法,而是另起门户,
只是名称相同而已,同样的,TC的test方法重载了TB的test方法,也与TA的test方法没有任
何关系。
在调用的例子中,虽然创建的都是TC对象,但@@2处是作为TA调用的,而@@3处是作为TB调
用的,如果@@1处是override的话,不会有任何差别;但如果改成virtual另立门户,结果就
不一样了。
 
真是经典解析呀
 
对你最有帮助的就是好好看看继承.
creation-zy 分析的已经挺透彻了.
TB的TEST在改成virtual后就不再继承TA了.所以会使TC也不再拥有TA里的过程.
而如果不改为virtual那么TB,TC也会继承TA里的过程

但是如果TB里的TEST改成virtual后,而在其事件中写上 inherited 那么就与写成override起到一样的作用了.
 
我的代码是这样的:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type

TA=class
protected
procedure test
virtual;
end;

TB=class(TA)
protected
procedure test
override
//改为virtual也是一样的效果,请大家指教
end;

TC=class(TB)
protected
procedure test
override;
end;

TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

{ TA }

procedure TA.test;
begin
showmessage('TA');
end;

{ TB }

procedure TB.test;
begin
inherited;
showmessage('TB');
end;

{ TC }

procedure TC.test;
begin
inherited;
showmessage('TC');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
tmp: TC;
begin
tmp:=TC.Create;
try
tmp.test;
finally
tmp.Free;
end;
end;

end.
 
猜想是由于函数名称一样,因此inherited;还会调用父类的相同名称的函数.
把tmp声明成TA再试试看效果.[:D]
 
>>猜想是由于函数名称一样,因此inherited;还会调用父类的相同名称的函数.
的确如此,Delphi的帮助表明,不带任何方法名的inherited将被指向父类的同名方法:

When inherited has no identifier after it, it refers to the inherited method
with the same name as the enclosing method or, if the enclosing method
is a message handler, to the inherited message handler for the same message.

为了确保在系统设计以及编码的过程中贯彻模式设计中的里氏代换原则,我们应该尽可能
的避免子类利用virtual关键字另起门户的现象。在上例中,如果将tmp声明为TA,那么TB以
及TC的test方法都不会起作用,相信这是设计者所不希望看到的(将一个对象变量声明为基
类,而在创建时用某个具体的子类来代替,这在程序代码中是很常见的)。
 
简单说来,就是Object Pascal的编译器规定就是这样的。
谢谢大家。
 
后退
顶部