“方法‘%s’”隐藏基类型“%s”的虚拟方法。到底隐藏了什么?
阅读 Ian Boyd 的构造函数系列问题后 (1, 2, < a href="https://stackoverflow.com/questions/3876484/delphi-how-to-add-a- Different-constructor-to-a-descendant">3, 4),我意识到我不太明白隐藏内容的字面意思。
我知道(如果我错了,请纠正我)override
的唯一目的是能够具有多态行为,以便运行时可以根据实例的实际类型解析方法 -与声明的类型相反。考虑以下代码:
type
TBase = class
procedure Proc1; virtual;
procedure Proc2; virtual;
end;
TChild = class(TBase)
procedure Proc1; override;
procedure Proc2; // <- [DCC Warning]
end;
procedure TBase.Proc1;
begin
Writeln('Base.Proc1');
end;
procedure TBase.Proc2;
begin
Writeln('Base.Proc2');
end;
procedure TChild.Proc1;
begin
inherited Proc1;
Writeln('Child.Proc1');
end;
procedure TChild.Proc2;
begin
inherited Proc2;
Writeln('Child.Proc2');
end;
var
Base: TBase;
begin
Base := TChild.Create;
Base.Proc1;
Writeln;
Base.Proc2;
Base.Free;
Readln;
end.
其输出:
Base.Proc1
Child.Proc1
Base.Proc2
TChild.Proc2
上的警告 声明此方法“将隐藏对同名基础方法的访问”。我看到的是,如果我不重写 Proc2,我就会失去该方法解析其实际类型的能力,而不是其基本类型的能力。如何隐藏对 base 方法的访问?
此外,在关于警告的文档中作为警告的解决方案,指出:
首先,您可以指定覆盖 使派生类的过程也 虚拟的,从而允许继承 要求仍引用原始内容 程序。
现在,如果我从“TChild”(无多态性)创建“TChild”实例,则非重写方法中的继承调用显然引用原始过程。如果我从“TBase”创建“Child”实例,调用甚至不会解析为“TChild”方法,我怎么能调用引用任何内容的“Inherited”呢?
我有什么误解吗?
After having read Ian Boyd's constructor series questions (1, 2, 3, 4), I realize I don't quite grasp the literal meaning on what's being hidden.
I know (correct me if I'm wrong) override
's sole purpose is to be able to have polymorphic behavior, so that run-time can resolve a method depending on the actual type of an instance - as opposed to the declared type. Consider the following code:
type
TBase = class
procedure Proc1; virtual;
procedure Proc2; virtual;
end;
TChild = class(TBase)
procedure Proc1; override;
procedure Proc2; // <- [DCC Warning]
end;
procedure TBase.Proc1;
begin
Writeln('Base.Proc1');
end;
procedure TBase.Proc2;
begin
Writeln('Base.Proc2');
end;
procedure TChild.Proc1;
begin
inherited Proc1;
Writeln('Child.Proc1');
end;
procedure TChild.Proc2;
begin
inherited Proc2;
Writeln('Child.Proc2');
end;
var
Base: TBase;
begin
Base := TChild.Create;
Base.Proc1;
Writeln;
Base.Proc2;
Base.Free;
Readln;
end.
Which outputs:
Base.Proc1
Child.Proc1Base.Proc2
The warning on TChild.Proc2
states that this method "will hide access to the base's method of the same name". What I see is, if I don't override Proc2
I loose the ability of the method's resolving to its actual type, not of its base type. How's that hiding access to base's method?
Further, down the documentation on the warning as a solution to the warning, it is stated that:
First, you could specify override to
make the derived class' procedure also
virtual, and thus allowing inherited
calls to still reference the original
procedure.
Now, if I create a 'TChild' instance from a 'TChild' (no polymorphism), the inherited call in the non-overridden method clearly refers to the original procedure. If I create the 'Child' instance from a 'TBase', the call does not even resolve to a 'TChild' method, how could I call 'Inherited' that would refer to anything at all?
What am I misunderstanding?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
除此之外,您将无法定义
,因为 TGrandChild 看到的 Proc2 是来自 TChild 的非虚拟 Proc2。 TChild.Proc2 对后代隐藏 TBase.Proc2。
编辑:
回答 Sertac 的评论:
这将输出
所以,似乎两次调用同一方法实际上是调用 2 个不同的方法。这使得代码更难理解(这不实用)并产生意想不到的行为。
Amongs other thing, you won't be able to define
because Proc2 that TGrandChild sees is the one from TChild that is not virtual. The TChild.Proc2 hide TBase.Proc2 from descendants.
EDIT:
In answer to Sertac's comment:
That will output
So, what seems to be a call to the same method twice is actually a call to 2 different methods. That makes code harder to understand (which is not practical) and yield unexpected behavior.
你想得太复杂了。隐藏并不意味着您完全无法访问原始内容。它只是意味着(您自己已经注意到了这一点)如果您有一个静态类型 TChild 的对象,并且您在其上调用 Proc2,它会调用 TChild 中的对象,而不是 TBase 中的对象。 Ken说的也是事实。
它警告您,因为原始是虚拟的,隐藏很可能不是人们在编写这样的代码时想要的。至少这是糟糕的编码风格。
You are thinking too complicated. Hiding doesn't mean you completely lose access to the original. It simply means (and you already noted this yourself) if you have an object of static type TChild, and you call Proc2 on it, it calls the one in TChild, and not the one in TBase. Also what Ken said is true.
It is warning you because the original is virtual and hiding is most likely not what people intend when writing code like that. At the very least it's bad coding style.
使用“重新引入”来抑制警告。
Use 'reintroduce' to suppress the warning.