Delphi:如何隐藏祖先构造函数? [英] Delphi: How to hide ancestor constructors?

查看:218
本文介绍了Delphi:如何隐藏祖先构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


更新:使用更简单的示例来解决问题,但没有回答原来接受的回答


给定以下类及其祖先:

  TComputer = class (TObject)
public
constructor Create(Teapot:string ='');
end;

TCellPhone = class(TComputer)
public
构造函数Create(Cup:Integer);超载;虚拟;
constructor Create(Cup:Integer; Teapot:string);超载;虚拟;
end;

现在 TCellPhone 有3个构造函数可见:




  • 杯:整数

  • 杯:整数; Teapot:string

  • Teapot:string =''



c $ c> TCellPhone ,使得祖先构造函数( Teapot:string ='')不可见,只留下声明的构造函数: p>


  • 杯:整数

  • 杯:整数; Teapot:string



具有后代构造函数隐藏了祖先:

  TCellPhone = class(TComputer)
public
构造函数Create(Cup:Integer);虚拟;
end;




  • 杯:整数



如果您需要保留
祖先构造函数和
子孙,您将标记
子孙作为重载

  TCellPhone = class(TComputer)
public
constructor Create(Cup:Integer);超载;虚拟;
end;




  • 杯:整数

  • Teapot:string =''


在这个问题的示例代码中,Delphi错误地将我的 overload 关键字:

  TCellPhone = class(TComputer)
public
constructor Create(Cup:Integer);超载;虚拟;
constructor Create(Cup:Integer; Teapot:string);超载;虚拟;
end;

认为:




  • 我想用 ancestor

  • 重载我的构造函数,当我真的想用 sibling



如何隐藏祖先构造函数?



可能无法使用当前定义的Delphi语言隐藏祖先,非虚拟的构造函数。 不可能 是有效的答案。






回复(失败)



尝试使用重新导入标记后代构造函数到我的随机添加关键字的模式,直到它工作):

  TCellPhone = class(TComputer)
public
constructor创建(Cup:Integer);再引入超载;虚拟;
constructor Create(Cup:Integer; Teapot:string);再引入超载;虚拟;
end;

但这没有效果,所有三个构造函数仍然可见。 :(






原始问题



具有构造函数不希望看到的类的下降:

  TEniac = class(TObject)
构造函数Create (PowerCord:TPowerCord = nil); //调用继承Create(b)

TComputer = class(TEniac)...
构造函数Create nil)

TCellPhone = class(TComputer)
构造函数创建(sim:TSimChip; UnlockCode:Integer); //调用继承Create(nil)

TiPhone = class(TCellPhone)
constructor创建(sim:TSimChip); //调用继承Create(sim,0)



注意:这是一个假设的例子,在现实世界中,祖先对象不能改变而不破坏现有的代码。


现在当有人使用 TiPhone 时,我不希望他们能够 / em> TEniac 的构造函数:

  iphone:= TiPhone。创建(powerCord);更糟糕的是,如果他们调用构造函数,他们完全错过我的构造函数,一切都在之间完成。这很容易调用错误的构造函数,所有这些都在IDE代码完成中可见,并将编译:

  TiPhone 。创建; 

,它们得到一个完全无效的对象。



i可以更改 TCellPhone 在这些构造函数中抛出异常:

  TCellPhone.Create(PowerCord:TPowercord)
begin
raise Exception.Create('Don''t use。');
end;

但是开发人员不会意识到他们调用错误的构造函数,直到客户有一天发现错误和罚款我们bazillions的美元。事实上,我 试图 找到所有我调用错误的构造函数 - 但我不知道如何让Delphi告诉我!

解决方案

在Delphi中创建派生类时,无法访问在祖先中引入的构造函数,因为你总是可以这样做:

  type 
TComputerClass = TComputer类;

var
CellPhoneClass:TComputerClass = TCellPhone;
手机:TCellPhone;
begin
CellPhone:= CellPhoneClass.Create('FUBAR')as TCellPhone;
end;

在任何派生类的代码中所做的任何事都不能阻止任何人调用用于创建派生类实例的TComputer.Create构造函数。



你最好做的是:

  TComputer = class(TObject)
public
constructor Create(Teapot:string ='');虚拟;
end;

TCellPhone = class(TComputer)
public
构造函数Create(Teapot:string ='');超载;覆盖;
constructor Create(Cup:Integer);超载;虚拟;
constructor Create(Cup:Integer; Teapot:string);超载;虚拟;
end;

在这种情况下,上面的代码至少会调用 TCellPhone.Create Teapot:string ='')而不是 TComputer.Create(Teapot:string ='')


Update: gutted the question with a simpler example, that isn't answered by the originally accepted answer

Given the following class, and its ancestor:

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;

Right now TCellPhone has 3 constructors visible:

  • Cup: Integer
  • Cup: Integer; Teapot: string
  • Teapot: string = ''

What do i do to TCellPhone so that the ancestor constructor (Teapot: string = '') is not visible, leaving only the declared constructors:

  • Cup: Integer
  • Cup: Integer; Teapot: string

Note: Usually the simple act of having a descendant constructor hides the ancestor:

TCellPhone = class(TComputer)
public
   constructor Create(Cup: Integer); virtual;
end;

  • Cup: Integer

And if you wanted to keep both the ancestor constructor and the descendant, you would mark the descendant as an overload:

TCellPhone = class(TComputer)
public
   constructor Create(Cup: Integer); overload; virtual;
end;

  • Cup: Integer
  • Teapot: string = ''

In this question's example code, Delphi is mistaking my overload keywords:

TCellPhone = class(TComputer)
public
   constructor Create(Cup: Integer); overload; virtual;
   constructor Create(Cup: Integer; Teapot: string); overload; virtual;
end;

to think that:

  • i want to overload my constructors with the ancestor,
  • when really i want to overload it with the sibling

How do i hide the ancestor constructor?

Note: It might be impossible to hide the ancestor, non-virtual, constructor using the Delphi language as it is currently defined. "Not possible" is a valid answer.


Attempted Answer (failed)

i tried marking the descendant constructors with reintroduce (falling back to my mode of randomly adding keywords until it works):

TCellPhone = class(TComputer)
public
   constructor Create(Cup: Integer); reintroduce; overload; virtual;
   constructor Create(Cup: Integer; Teapot: string); reintroduce; overload; virtual;
end;

But that didn't work, all three constructors are still visible. :(


Original Question

i have an object that descends from a class that has constructors don't want to see:

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)

Note: This is a hypothetical example. As in the real world, the ancestor objects cannot be changed without breaking existing code.

Now when someone's using TiPhone i don't want them even being able to see the constructor from TEniac:

iphone := TiPhone.Create(powerCord);

Worse still: if they call that constructor, they completely miss my constructor, and everything done in between. It's pretty easy to call the wrong constructor, all of them are visible in the IDE code-completion, and will compile:

TiPhone.Create;

and they get a completely invalid object.

i could change TCellPhone to throw an exception in those constructors:

TCellPhone.Create(PowerCord: TPowercord)
begin
   raise Exception.Create('Don''t use.');
end;

But developers won't realize they're calling the wrong constructor until the customer finds the error one day and fines us bazillions of dollars. In fact, i'm trying to find everywhere i call the wrong constructor - but i can't figure out how to make Delphi tell me!

解决方案

It's impossible to ever make a constructors introduced in an ancestor inaccessible for the creation of a derived class in Delphi because you can always do this:

type
  TComputerClass = class of TComputer;

var
  CellPhoneClass: TComputerClass = TCellPhone;
  CellPhone : TCellPhone;
begin
  CellPhone := CellPhoneClass.Create('FUBAR') as TCellPhone;
end;

Nothing you could do in the code of any derived class would ever be able to prevent anyone from calling the TComputer.Create constructor for creating an instance of the derived class.

The best you could do is:

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;

In that case the code above would at least be calling TCellPhone.Create(Teapot: string='') instead of TComputer.Create(Teapot: string='')

这篇关于Delphi:如何隐藏祖先构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆