这是我previous question on how to hide inherited constructors的变体。你如何隐藏继承的方法:
在Delphi允许您构造COM对象的方式之后进行建模:
CoDOMDocument = class
class function Create: IXMLDOMDocument2;
end;
我有一个工厂,它创建一个实现接口的对象:
CoCondition = class
public
class function Create: ICondition;
end;
这很好用。虽然在祖先中有一个名为Create
的方法,但它工作正常。它有效,因为我没有overload
关键字。只要我添加overload
关键字:Delphi将允许继承的Create
方法“闪耀”:
CoCondition = class
public
class function Create: ICondition; overload;
end;
现在CoCondition
有两种Create
方法:
class function CoCondition.Create: ICondition;
constructor TObject.Create;
你要打电话给哪一个是模棱两可的。修复,显然是没有overload
关键字(为什么你,你没有重载任何东西?)。好吧,事实证明我我超载了一些东西:
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;
由于我有overload
个关键字,因此该类有五个重载,而不仅仅是我想要的四个:
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;
我只希望我的四个重载存在,而没有其他。即我想隐藏任何祖先方法。
如何隐藏祖先方法?
我也试着明确地声明祖先方法,但保护它,所以没有人可以得到它:
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;
但我认为所有酷孩子都隐藏了他们的物品。
答案 0 :(得分:6)
隐藏方法是不可能的,因为它违背了面向对象编程的基础。
即使一种语言支持隐藏,你也可以随时解决它。
例如,如果您创建具有TAnimal
属性的Name
类,然后创建一个TNamelessAnimal
类,您要隐藏Name
属性。
现在,您可以将TNamelessAnimal
实例转换为TAnimal
引用,并仍然可以访问Name
属性。
这是完全符合逻辑的,因为TNamelessAnimal
是TAnimal
,因此具有Name
属性。
- 的Jeroen
答案 1 :(得分:4)
Delphi不支持隐藏方法,因为它不符合逻辑。假设祖先TAncestor有公共方法AMethod。现在声明TDescendant = class(TAncestor)并将其覆盖AMethod作为protected。现在,用户可以简单地将您的TDescendant转换为TAncestor并访问应该被隐藏的方法。我不知道任何面向对象的语言是否支持祖先中的隐藏方法,但我怀疑是否存在。
答案 2 :(得分:3)
“隐藏”祖先方法的最佳方法是使用对您而言重要的方法名称声明一个接口...例如:
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;
一旦开始使用界面,就很难停止。
答案 3 :(得分:1)
不要费心去争取它。只需将所有实现方法和属性放入其自身单元的受保护范围内,因此它将强制您使用接口。其他选择是使用与param(s)的其他Create方法不同的名称,并删除重载关键字
干杯
答案 4 :(得分:0)
使用“reintroduce”指令标记命名方法的新“版本”:
CoCondition = class
public
class function Create: ICondition; reintroduce;
end;
这允许您“重新引入”具有不同参数的方法名称。
但请注意,重新引入与重载(虚拟方法)不同...如果使用类引用调用这些方法,则最终调用的Create方法将取决于所涉及的类引用的特定类型,而不是而不是调用“最衍生的版本”。
另请注意,您无法减少声明的继承方法的可见性...如果存在继承的“公共”Create方法,则重新引入“受保护”的Create方法实际上不会隐藏公众一个人。