Delphi:如何隐藏祖先方法?

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的方法,它也可以正常工作。它之所以有效,

这是我的一个变体。如何隐藏继承的方法:

按照Delphi构建COM对象的方式进行建模:

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;