Delphi:如何隐藏祖先方法?

发布于 2024-10-13 05:02:27 字数 3655 浏览 3 评论 0原文

这是我的上一个关于如何隐藏继承的构造函数的问题的变体。如何隐藏继承的方法:

按照 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

萌能量女王 2024-10-20 05:02:27

隐藏方法是不可能的,因为它违背了面向对象编程的基本原理。

即使一种语言支持隐藏,您也可以随时解决它。

例如,如果您创建一个具有 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 a Name property, and then you create a TNamelessAnimal class where you want to hide the Name property.
Now then you could cast a TNamelessAnimal instance into a TAnimal reference, and still access the Name property.
This is perfectly logical, since a TNamelessAnimal, is a TAnimal, and therefore has the Name property.

--jeroen

夜访吸血鬼 2024-10-20 05:02:27

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.

江挽川 2024-10-20 05:02:27

我“隐藏”祖先方法的最佳方法是声明一个接口,其中包含对您重要的方法的名称...例如:

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;

一旦您开始使用接口,就很难停止。

My best way to 'hide' ancestor methods is to declare an interface with the names of the methods that matter to you...eg:

IMyInterface = interface
  procedure One;
  procedure Two;
end;

Then, implement these methods in your class, exposing your class as implementing IMyInterface eg:

TMyClass = class( TInterfacedObject, IMyInterface )
PUBLIC
  procedure One;
  procedure Two;
end;

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:

IMyInterface = interface
  function GetSomething : integer;
  procedure SetSomething( AValue : integer );
  property  Something : integer; read GetSomething write SetSomething;
end;

Once you start using interfaces it will be hard to stop.

浅浅 2024-10-20 05:02:27

使用“reintroduce”指令标记命名方法的新“版本”:

CoCondition = class
public
   class function Create: ICondition; reintroduce;
end;

这允许您“重新引入”具有不同参数的方法名称。

但请注意,重新引入与重载(虚拟方法)不同...如果您使用类引用调用这些方法,您最终调用的 Create 方法将取决于所涉及的类引用的特定类型,而不是调用“最衍生版本”。

另请注意,您无法减少继承方法的声明可见性...如果继承了“公共”Create 方法,则重新引入“受保护”Create 方法实际上不会隐藏公共方法根本不。

Mark your new "version" of the named method with the "reintroduce" directive:

CoCondition = class
public
   class function Create: ICondition; reintroduce;
end;

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.

清风无影 2024-10-20 05:02:27

不必费心去争夺它。只需将所有实现方法和属性放入其自身单元的受保护范围中即可,因此它将强制您使用接口。其他选择是为其他带有参数的 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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文