Ian*_*oyd 11 delphi constructor delphi-5 constructor-chaining
更新:用一个更简单的例子来解决问题,原来接受的答案没有回答
鉴于以下类及其祖先:
TComputer = class(TObject)
public
constructor Create(Teapot: string='');
end;
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer); overload; virtual;
constructor Create(Cup: Integer; Teapot: string); overload; virtual;
end;
Run Code Online (Sandbox Code Playgroud)
现在TCellPhone
有3个构造函数可见:
我该怎么做才能TCellPhone
使祖先构造函数(Teapot: string = ''
)不可见,只留下声明的构造函数:
注:通常简单的行为有一个后代的构造函数隐藏了祖先:
Run Code Online (Sandbox Code Playgroud)TCellPhone = class(TComputer) public constructor Create(Cup: Integer); virtual; end;
- 杯子:整数
如果你想保留祖先构造函数和后代,你可以将后代标记为
overload
:Run Code Online (Sandbox Code Playgroud)TCellPhone = class(TComputer) public constructor Create(Cup: Integer); overload; virtual; end;
- 杯子:整数
- 茶壶:string =''
在这个问题的示例代码中,Delphi误解了我的overload
关键字:
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer); overload; virtual;
constructor Create(Cup: Integer; Teapot: string); overload; virtual;
end;
Run Code Online (Sandbox Code Playgroud)
认为:
我如何隐藏祖先构造函数?
注意:可能无法使用当前定义的Delphi语言隐藏祖先,非虚拟构造函数."不可能"是一个有效的答案.
我试着标记后代构造函数reintroduce
(回到我的模式,随机添加关键字,直到它工作):
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer); reintroduce; overload; virtual;
constructor Create(Cup: Integer; Teapot: string); reintroduce; overload; virtual;
end;
Run Code Online (Sandbox Code Playgroud)
但这不起作用,所有三个构造函数仍然可见.:(
我有一个对象,它来自一个有构造函数不想看到的类:
TEniac = class(TObject)
constructor Create(PowerCord: TPowerCord=nil); //calls inherited Create
TComputer = class(TEniac) ...
constructor Create(PowerCord: TPowerCord=nil); //calls inherited Create(nil)
TCellPhone = class(TComputer)
constructor Create(sim: TSimChip; UnlockCode: Integer); //calls inherited Create(nil)
TiPhone = class(TCellPhone)
constructor Create(sim: TSimChip); //calls inherited Create(sim, 0)
Run Code Online (Sandbox Code Playgroud)
注意:这是一个假设的例子.与现实世界一样,如果不破坏现有代码,则无法更改祖先对象.
现在当有人使用TiPhone
我不希望他们甚至能够从以下方面看到构造函数时TEniac
:
iphone := TiPhone.Create(powerCord);
Run Code Online (Sandbox Code Playgroud)
更糟糕的是:如果他们称之为构造函数,他们会完全错过我的构造函数,并且完成所有工作.调用错误的构造函数非常容易,所有这些都在IDE代码完成中可见,并将编译:
TiPhone.Create;
Run Code Online (Sandbox Code Playgroud)
他们得到一个完全无效的对象.
我可以更改TCellPhone
为在这些构造函数中抛出异常:
TCellPhone.Create(PowerCord: TPowercord)
begin
raise Exception.Create('Don''t use.');
end;
Run Code Online (Sandbox Code Playgroud)
但是开发人员不会意识到他们正在调用错误的构造函数,直到客户有一天发现错误并罚款我们的数百美元.事实上,我试图找到我称之为错误的构造函数 - 但我无法弄清楚如何让Delphi告诉我!
如果我没记错的话,reintroduce
应该帮助虚拟方法.
在重新引入指令禁止有关隐藏先前声明的虚拟方法的编译器警告.如果要使用新方法隐藏继承的虚拟方法,请使用重新引入.
要回答你更新的问题 - 我认为在直接派生类中隐藏非虚拟构造函数是不可能的,但我尝试了以下成功:
TComputer = class(TObject)
public
constructor Create(Teapot: string='');
end;
TIndermediateComputer = class(TComputer)
protected
// hide the constructor
constructor Create;
end;
TCellPhone = class(TIndermediateComputer)
public
constructor Create(Cup: Integer); overload; virtual;
constructor Create(Cup: Integer; Teapot: string); overload; virtual;
end;
Run Code Online (Sandbox Code Playgroud)
为了在Delphi中创建派生类,不可能在祖先中引入构造函数是不可能的,因为你总是可以这样做:
type
TComputerClass = class of TComputer;
var
CellPhoneClass: TComputerClass = TCellPhone;
CellPhone : TCellPhone;
begin
CellPhone := CellPhoneClass.Create('FUBAR') as TCellPhone;
end;
Run Code Online (Sandbox Code Playgroud)
你在任何派生类的代码中所做的任何事情都无法阻止任何人调用TComputer.Create构造函数来创建派生类的实例.
你能做的最好的事情是:
TComputer = class(TObject)
public
constructor Create(Teapot: string=''); virtual;
end;
TCellPhone = class(TComputer)
public
constructor Create(Teapot: string=''); overload; override;
constructor Create(Cup: Integer); overload; virtual;
constructor Create(Cup: Integer; Teapot: string); overload; virtual;
end;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,上面的代码至少会调用TCellPhone.Create(Teapot: string='')
而不是TComputer.Create(Teapot: string='')
不要只在被覆盖的无效构造函数中引发“不要使用”异常,而是考虑在它们变得无效的类中将它们标记为弃用。当这些无效的构造函数被错误地使用时,这应该会产生很好的编译器警告。
TCellPhone = class(TComputer)
constructor Create(PowerCord: TPowerCord=nil); deprecated;
constructor Create(sim: TSimChip; UnlockCode: Integer); //calls inherited Create(nil)
Run Code Online (Sandbox Code Playgroud)
此外,根据需要使用覆盖或重新引入。
归档时间: |
|
查看次数: |
4150 次 |
最近记录: |