Delphi:如何隐藏祖先方法?
这是我的上一个关于如何隐藏继承的构造函数的问题的变体。如何隐藏继承的方法:
按照 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;
但我认为所有酷孩子都隐藏他们的对象。
This is a variation on my previous question on how to hide inherited constructors. How do you hide inherited methods:
Modelling after the way Delphi lets you construct COM objects:
CoDOMDocument = class
class function Create: IXMLDOMDocument2;
end;
i have a factory that creates an object that implements an interface:
CoCondition = class
public
class function Create: ICondition;
end;
This works fine and great. It works fine, even though there's a method in the ancestor called Create
. It works because i don't have the overload
keyword present. As soon as i add the overload
keyword: Delphi will allow the inherited Create
method to "shine through":
CoCondition = class
public
class function Create: ICondition; overload;
end;
So now CoCondition
has two Create
method available:
class function CoCondition.Create: ICondition;
constructor TObject.Create;
And it's ambiguous over which one you want to call. The fix, obviously is to just not have the overload
keyword (Why would you, you're not overloading anything?). Well it turns out i am overloading something:
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;
Since i have the overload
keyword, the class has five overloads, rather than just the four i want:
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 only want my four overloads to be present, and no others. i.e. i want to hide any ancestor methods.
How do i hide ancestor methods?
i also tried explicitely declaring the ancestor method, but having it in protected, so nobody can get at it:
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;
But that doesn't compile because of ambigious overload of unparametered Create()
.
i also considered:
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;
But rejected it.
i could just expose the object that implements the object:
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;
But i thought all the cool kids hide their objects.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
隐藏方法是不可能的,因为它违背了面向对象编程的基本原理。
即使一种语言支持隐藏,您也可以随时解决它。
例如,如果您创建一个具有
Name
属性的TAnimal
类,然后您创建一个要隐藏TNamelessAnimal
类的TNamelessAnimal
类。代码>名称属性。现在,您可以将
TNamelessAnimal
实例转换为TAnimal
引用,并且仍然访问Name
属性。这是完全合乎逻辑的,因为
TNamelessAnimal
是一个TAnimal
,因此具有Name
属性。——杰罗恩
Hiding methods is not possible, because it goes against the fundamentals of object oriented programming.
Even if a language would support hiding, you could always work around it.
If for instance, if you create a
TAnimal
class with aName
property, and then you create aTNamelessAnimal
class where you want to hide theName
property.Now then you could cast a
TNamelessAnimal
instance into aTAnimal
reference, and still access theName
property.This is perfectly logical, since a
TNamelessAnimal
, is aTAnimal
, and therefore has theName
property.--jeroen
Delphi 不支持隐藏方法,因为它不符合逻辑。假设祖先 TAncestor 有公共方法 AMethod。现在声明 TDescendant=class(TAncestor) 并让它覆盖 AMethod 作为受保护的。现在,用户可以简单地将 TDescendant 转换为 TAncestor 并访问本应隐藏的方法。我不知道是否有任何面向对象的语言支持在祖先中隐藏方法,但我怀疑是否有。
Hiding a method is not supported in Delphi simply because it's not logical. Suppose ancestor TAncestor has public method AMethod. Now declare TDescendant=class(TAncestor) and have it override AMethod as protected. Now the user can simply cast your TDescendant to TAncestor and access the method, which was supposed to be hidden. I don't know if any object-oriented language supports hiding methods in ancestors, but I doubt there are any.
我“隐藏”祖先方法的最佳方法是声明一个接口,其中包含对您重要的方法的名称...例如:
然后,在您的类中实现这些方法,将您的类公开为实现 IMyInterface 例如:
在代码的其他地方,将类的实例作为 IMyInterface (而不是 TMyClass)传递。这巧妙地隐藏了类中的所有内部结构,并将代码分解为良好分区的模块。
您会惊讶地发现接口声明可以“看起来”像一个类,即也具有属性,例如,这是合法的并且非常有用:
一旦您开始使用接口,就很难停止。
My best way to 'hide' ancestor methods is to declare an interface with the names of the methods that matter to you...eg:
Then, implement these methods in your class, exposing your class as implementing IMyInterface eg:
Elsewhere in your code, pass around the instance of your class as an IMyInterface (not TMyClass) instead. This neatly hides ALL internals in your class and breaks up your code into nicely partioned modules.
You will be amazed how the interface declaration can be made to 'look' like a class i.e with properties too, for example this is legal and highly useful:
Once you start using interfaces it will be hard to stop.
使用“reintroduce”指令标记命名方法的新“版本”:
这允许您“重新引入”具有不同参数的方法名称。
但请注意,重新引入与重载(虚拟方法)不同...如果您使用类引用调用这些方法,您最终调用的 Create 方法将取决于所涉及的类引用的特定类型,而不是调用“最衍生版本”。
另请注意,您无法减少继承方法的声明可见性...如果继承了“公共”Create 方法,则重新引入“受保护”Create 方法实际上不会隐藏公共方法根本不。
Mark your new "version" of the named method with the "reintroduce" directive:
This allows you to "reintroduce" a method name with different parameters.
But note that reintroducing is not the same as overloading (a virtual method)... if you invoke these methods using a class reference the Create method you end up invoking will depend on the specific type of the class reference involved, rather than invoking the "most derived version".
Note also that you cannot reduce the declared visibility of an inherited method... if there is a "public" Create method inherited, then reintroducing a "protected" Create method won't actually hide the public one at all.
不必费心去争夺它。只需将所有实现方法和属性放入其自身单元的受保护范围中即可,因此它将强制您使用接口。其他选择是为其他带有参数的 Create 方法使用不同的名称,并删除重载关键字
干杯
Do not bother to fight over it. Just put all your implementing methods and properties into protected scope of its own unit hence it will force you to use interface. Other choice is use different name for other Create methods with param(s) and remove the overload keyword
Cheers