覆盖VS方法隐藏 [英] Overriding vs method hiding
问题描述
我有点困惑覆盖与隐藏在C#中的方法。每个实际用途也将是AP preciated,以及用于<青霉>时的人会使用每个的说明
我感到困惑压倒一切 - 我们为什么要重写?从我目前了解到的是,通过overring我们可以派生类的方法提供所需的实现,不改变签名。
如果我不会覆盖父类的方法和我更改在子类中的方法,将进行更改的超类的方法?
我也困惑以下 - 这是什么展示
? A级
{
虚拟M1()
{
console.writeline(再见了所有);
}
}B类:一
{
覆盖M1()
{
console.writeLine(给所有);
}
}C类
{
A中新= A();
B B =新的B();
A = B; (这是什么)
a.m1(); //这是什么将打印,为什么? B = A; //这里会发生什么?
}
考虑:
公共类BaseClass的
{
公共无效WriteNum()
{
Console.WriteLine(12);
}
公共虚拟无效WriteStr()
{
Console.WriteLine(ABC);
}
}公共类DerivedClass:BaseClass的
{
新公共无效WriteNum()
{
Console.WriteLine(42);
}
公共覆盖无效WriteStr()
{
Console.WriteLine(XYZ);
}
}
/ * ... * /
BaseClass的isReallyBase =新的BaseClass();
BaseClass的isReallyDerived =新DerivedClass();
DerivedClass isClearlyDerived =新DerivedClass();isReallyBase.WriteNum(); //写12
isReallyBase.WriteStr(); //写ABC
isReallyDerived.WriteNum(); //写12
isReallyDerived.WriteStr(); //写XYZ
isClearlyDerived.WriteNum(); //写42
isClearlyDerived.writeStr(); //写XYZ
重载是典型的面向对象的方式中,派生类可以有比基类更具体的行为(在某些语言中,你已经别无选择,只能这样做)。当一个虚拟方法调用的对象上,则该方法的最派生版本被调用。因此,即使我们用 isReallyDerived
处理为的BaseClass
再定义的功能 DerivedClass
被使用。
隐藏意味着我们有一个完全不同的方法。当我们调用 WriteNum()
在 isReallyDerived
那么有没有办法知道,有一个不同的 WriteNum()
在 DerivedClass
所以它不叫。当我们正在处理的对象的,因为它只能被称为 DerivedClass
。
大多数时候藏身的是坏的。一般情况下,要么你应该有一个方法,虚拟如果有可能在派生类中进行更改,并在派生类中重写它。然而有两件事是有用
-
向前兼容性。如果
DerivedClass
有一个DoStuff()
方法,再后来就的BaseClass
改为添加一个DoStuff()
方法,(记住,它们可能由不同的人来写,并在不同的组件中存在),然后在成员藏身的禁令将有突然来了DerivedClass
越野车没有它改变。此外,如果新的DoStuff()
在的BaseClass
是虚拟的,然后自动做出,关于DerivedClass
它的覆盖可能会导致被称为pre-现有的方法时,它不应该。因此,它是很好的隐藏是默认的(我们使用新
要清楚,我们肯定要藏起来,但在离开它隐藏,并发出关于编译警告)。 -
可怜的人的协方差。考虑一个
克隆()
方法上的的BaseClass
返回一个新的的BaseClass
这就是创建一个副本。在DerivedClass
覆盖这将创建一个DerivedClass
,但返回它作为一个的BaseClass
,这是不一样有用。我们可以做的是有一个虚保护CreateClone()
被覆盖。在的BaseClass
我们有一个克隆()
返回这个结果 - 一切都很好 - 在DerivedClass
我们隐藏这一个新的克隆()
返回一个DerivedClass
。调用克隆()
在的BaseClass
将始终返回的BaseClass
参考,这将是一个的BaseClass
值或DerivedClass
值为宜。调用克隆()
在DerivedClass
将返回DerivedClass
价值,这是我们会在这方面想要什么。有这个原理的其他变体,但是应该指出的是它们都是pretty稀有
在第二种情况下要注意的重要一点是,我们使用隐藏precisely为删除惊喜调用code,如使用<$ C $的人C> DerivedClass 可以合理预期公司克隆()
返回 DerivedClass
。的任何的它可以被称为方式将结果保持一致彼此。大多数情况下隐藏的风险引进的惊喜,这就是为什么他们一般都令人难以接受的。这其中是有道理的precisely,因为它解决了很的问题,往往隐藏介绍。
在所有的,隐藏有时是必要的,有用的很少,但一般不好,所以要十分小心了。
I am a bit confused about overriding vs. hiding a method in C#. Practical uses of each would also be appreciated, as well as an explanation for when one would use each.
I am confused about overriding - why do we override? What I have learnt so far is that by overring we can provide desired implementation to a method of a derived class, without changing the signature.
If I don't override the method of the superclass and I make changes to the method in the sub class, will that make changes to the super class method ?
I am also confused about the following - what does this demonstrate?
class A
{
virtual m1()
{
console.writeline("Bye to all");
}
}
class B : A
{
override m1()
{
console.writeLine("Hi to all");
}
}
class C
{
A a = new A();
B b = new B();
a = b; (what is this)
a.m1(); // what this will print and why?
b = a; // what happens here?
}
Consider:
public class BaseClass
{
public void WriteNum()
{
Console.WriteLine(12);
}
public virtual void WriteStr()
{
Console.WriteLine("abc");
}
}
public class DerivedClass : BaseClass
{
public new void WriteNum()
{
Console.WriteLine(42);
}
public override void WriteStr()
{
Console.WriteLine("xyz");
}
}
/* ... */
BaseClass isReallyBase = new BaseClass();
BaseClass isReallyDerived = new DerivedClass();
DerivedClass isClearlyDerived = new DerivedClass();
isReallyBase.WriteNum(); // writes 12
isReallyBase.WriteStr(); // writes abc
isReallyDerived.WriteNum(); // writes 12
isReallyDerived.WriteStr(); // writes xyz
isClearlyDerived.WriteNum(); // writes 42
isClearlyDerived.writeStr(); // writes xyz
Overriding is the classic OO way in which a derived class can have more specific behaviour than a base class (in some languages you've no choice but to do so). When a virtual method is called on an object, then the most derived version of the method is called. Hence even though we are dealing with isReallyDerived
as a BaseClass
then functionality defined in DerivedClass
is used.
Hiding means that we have a completely different method. When we call WriteNum()
on isReallyDerived
then there's no way of knowing that there is a different WriteNum()
on DerivedClass
so it isn't called. It can only be called when we are dealing with the object as a DerivedClass
.
Most of the time hiding is bad. Generally, either you should have a method as virtual if its likely to be changed in a derived class, and override it in the derived class. There are however two things it is useful for:
Forward compatibility. If
DerivedClass
had aDoStuff()
method, and then later onBaseClass
was changed to add aDoStuff()
method, (remember that they may be written by different people and exist in different assemblies) then a ban on member hiding would have suddenly madeDerivedClass
buggy without it changing. Also, if the newDoStuff()
onBaseClass
was virtual, then automatically making that onDerivedClass
an override of it could lead to the pre-existing method being called when it shouldn't. Hence it's good that hiding is the default (we usenew
to make it clear we definitely want to hide, but leaving it out hides and emits a warning on compilation).Poor-man's covariance. Consider a
Clone()
method onBaseClass
that returns a newBaseClass
that's a copy of that created. In the override onDerivedClass
this will create aDerivedClass
but return it as aBaseClass
, which isn't as useful. What we could do is to have a virtual protectedCreateClone()
that is overridden. InBaseClass
we have aClone()
that returns the result of this - and all is well - inDerivedClass
we hide this with a newClone()
that returns aDerivedClass
. CallingClone()
onBaseClass
will always return aBaseClass
reference, which will be aBaseClass
value or aDerivedClass
value as appropriate. CallingClone()
onDerivedClass
will return aDerivedClass
value, which is what we'd want in that context. There are other variants of this principle, however it should be noted that they are all pretty rare.
An important thing to note with the second case, is that we've used hiding precisely to remove surprises to the calling code, as the person using DerivedClass
might reasonably expect its Clone()
to return a DerivedClass
. The results of any of the ways it could be called are kept consistent with each other. Most cases of hiding risk introducing surprises, which is why they are generally frowned upon. This one is justified precisely because it solves the very problem that hiding often introduces.
In all, hiding is sometimes necessary, infrequently useful, but generally bad, so be very wary of it.
这篇关于覆盖VS方法隐藏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!