Delphi:如何隐藏祖先方法?
这是我的一个变体。如何隐藏继承的方法: 按照Delphi构建COM对象的方式进行建模:Delphi:如何隐藏祖先方法?,delphi,inheritance,factory,factory-pattern,Delphi,Inheritance,Factory,Factory Pattern,这是我的一个变体。如何隐藏继承的方法: 按照Delphi构建COM对象的方式进行建模: CoDOMDocument = class class function Create: IXMLDOMDocument2; end; 我有一个工厂,它创建一个实现接口的对象: CoCondition = class public class function Create: ICondition; end; 这很好用。即使在祖先中有一个名为Create的方法,它也可以正常工作。它之所以有效,
CoDOMDocument = class
class function Create: IXMLDOMDocument2;
end;
我有一个工厂,它创建一个实现接口的对象:
CoCondition = class
public
class function Create: ICondition;
end;
这很好用。即使在祖先中有一个名为Create
的方法,它也可以正常工作。它之所以有效,是因为我没有重载
关键字。只要我添加重载
关键字:Delphi将允许继承的创建
方法“闪耀”:
所以现在,CoCondition
有两个Create
方法可用:
class function CoCondition.Create: ICondition;
constructor TObject.Create;
你想打哪一个电话是不明确的。很明显,解决方法就是不要使用重载
关键字(为什么你会这样做,你没有重载任何东西?)。事实证明我是超载的:
CoCondition = class
public
class function Create: ICondition; overload;
class function Create(const ConditionType: TConditionType): ICondition; overload;
class function Create(const PropertyName: string; const Operation: TConditionOperation; const Value: Variant): ICondition; overload;
class function Create(const ConditionType: TConditionType; const SubConditions: IInterfaceList): ICondition; overload;
end;
由于我有重载
关键字,该类有五个重载,而不是我想要的四个:
class function CoCondition.Create: ICondition;
class function CoCondition.Create(const ConditionType: TConditionType): ICondition; overload;
class function CoCondition.Create(const PropertyName: string; const Operation: TConditionOperation; const Value: Variant): ICondition; overload;
class function CoCondition.Create(const ConditionType: TConditionType; const SubConditions: IInterfaceList): ICondition; overload;
constructor TObject.Create;
我只希望我的四个重载存在,而不希望其他重载存在。i、 我想隐藏任何祖先方法
如何隐藏祖先方法
我还尝试明确声明祖先方法,但将其置于受保护状态,因此没有人能够获得它:
CoCondition = class
protected
constructor Create; overload;
public
class function Create(): ICondition; overload;
class function Create(const ConditionType: TConditionType): ICondition; overload;
class function Create(const PropertyName: string; const Operation: TConditionOperation; const Value: Variant): ICondition; overload; //leaf
class function Create(const ConditionType: TConditionType; const SubConditions: IInterfaceList): ICondition; overload; //AND/OR/NOT children
end;
但由于未经参数化的Create()
的含糊不清的重载,这无法编译
我还考虑到:
CoCondition = class
public
class function Make(): ICondition; overload;
class function Make(const ConditionType: TConditionType): ICondition; overload;
class function Make(const PropertyName: string; const Operation: TConditionOperation; const Value: Variant): ICondition; overload; //leaf
class function Make(const ConditionType: TConditionType; const SubConditions: IInterfaceList): ICondition; overload; //AND/OR/NOT children
end;
但他拒绝了
我可以公开实现该对象的对象:
TCondition = class(TInterfacedObject, ICondition)
...
public
constructor Create; overload;
constructor Create(const ConditionType: TConditionType); overload;
constructor Create(const PropertyName: string; const Operation: TConditionOperation; const Value: Variant); overload; //leaf
constructor Create(const ConditionType: TConditionType; const SubConditions: IInterfaceList); overload; //AND/OR/NOT children
end;
但是我认为所有酷孩子都会隐藏他们的对象。隐藏方法在Delphi中不受支持,因为它不符合逻辑。假设祖先TAncestor拥有公共方法AMethod。现在声明tdescentant=class(TAncestor)并将其覆盖为受保护的AMethod。现在,用户只需将TDescendant转换为TAncestor并访问该方法,该方法本应隐藏。我不知道是否有面向对象的语言支持在祖先中隐藏方法,但我怀疑是否有 隐藏方法是不可能的,因为它违背了面向对象编程的基本原理 即使一种语言支持隐藏,您也可以随时解决它 例如,如果您创建一个带有
名称
属性的TAnimal
类,然后创建一个TNamelessAnimal
类,在其中隐藏名称
属性。现在,您可以将
TNamelessAnimal
实例强制转换为TAnimal
引用,并且仍然可以访问Name
属性。这是完全合乎逻辑的,因为
TNamelessAnimal
是TAnimal
,因此具有Name
属性
--jeroen用“重新引入”指令标记命名方法的新“版本”:
CoCondition = class
public
class function Create: ICondition; reintroduce;
end;
这允许您使用不同的参数“重新引入”方法名称
但请注意,重新引入与重载(虚拟方法)不同。。。如果使用类引用调用这些方法,那么最终调用的Create方法将取决于所涉及的类引用的特定类型,而不是调用“最派生的版本”
还要注意,不能降低继承方法的声明可见性。。。如果继承了一个“public”Create方法,那么重新引入一个“protected”Create方法实际上根本不会隐藏这个公共方法。我“隐藏”祖先方法的最好方法是声明一个接口,其中包含对您有影响的方法的名称……例如:
IMyInterface = interface
procedure One;
procedure Two;
end;
然后,在类中实现这些方法,将类公开为实现IMyInterface,例如:
TMyClass = class( TInterfacedObject, IMyInterface )
PUBLIC
procedure One;
procedure Two;
end;
在代码的其他地方,将类的实例作为IMyInterface(而不是TMyClass)传递。这巧妙地隐藏了类中的所有内部构件,并将代码分解为分区良好的模块
您会惊讶于接口声明如何“看起来”像一个类,也就是说,它也有属性,例如,这是合法的,非常有用:
IMyInterface = interface
function GetSomething : integer;
procedure SetSomething( AValue : integer );
property Something : integer; read GetSomething write SetSomething;
end;
一旦开始使用接口,就很难停止使用。不要为它而争吵。只需将所有实现方法和属性放在它自己单元的受保护范围内,它就会迫使您使用接口。另一种选择是为其他具有param的Create方法使用不同的名称,并删除重载关键字
干杯好吧,你不应该使用Create,因为Create用于构造函数,而这不是构造函数。>>但我认为所有酷孩子都会隐藏他们的对象。@David Heffernan,但Borland做到了:(@Ian当然,您从Embarcadero引用的代码可能是由typelib导入程序生成的。无论如何,他们并没有试图重载。无论如何,我坚持认为Create应该保留给构造函数。我会将这些方法命名为
CreateInstance
,然后使用它。“can simply case”应该是“can simply cast”,我想?因为这些是类方法,所以这个参数不适用。在类函数运行之前没有实例。@David,那又怎样?有一个类本身,可以直接引用。“我不知道是否有面向对象的语言支持在祖先中隐藏方法,但我怀疑是否有。”Delphi支持在祖先中隐藏方法。你只需声明一个同名的方法,嘿,presto!你就隐藏了一个方法。@David,不,你错了。刚刚在Delphi 5中测试过-向祖先强制转换成功地击败了在后代中使用同名方法的任何把戏。好吧,你可以隐藏祖先方法;只是当你使用<代码>重载。但“无法完成”的答案可能与它将得到的答案一样正确。因为这些是类方法,所以此参数不适用。在类函数运行之后才有实例。确实如此;只要将类引用强制转换为祖先引用中,您就完成了。例如,Name
是cl时ass属性,然后TAni
IMyInterface = interface
function GetSomething : integer;
procedure SetSomething( AValue : integer );
property Something : integer; read GetSomething write SetSomething;
end;