覆盖VS方法隐藏 [英] Overriding vs method hiding

查看:105
本文介绍了覆盖VS方法隐藏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有点困惑覆盖与隐藏在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

大多数时候藏身的是坏的。一般情况下,要么你应该有一个方法,虚拟如果有可能在派生类中进行更改,并在派生类中重写它。然而有两件事是有用


  1. 向前兼容性。如果 DerivedClass 有一个 DoStuff()方法,再后来就的BaseClass 改为添加一个 DoStuff()方法,(记住,它们可能由不同的人来写,并在不同的组件中存在),然后在成员藏身的禁令将有突然来了 DerivedClass 越野车没有它改变。此外,如果新的 DoStuff()的BaseClass 是虚拟的,然后自动做出,关于 DerivedClass 它的覆盖可能会导致被称为pre-现有的方法时,它不应该。因此,它是很好的隐藏是默认的(我们使用要清楚,我们肯定要藏起来,但在离开它隐藏,并发出关于编译警告)。


  2. 可怜的人的协方差。考虑一个克隆()方法上的的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:

  1. Forward compatibility. If DerivedClass had a DoStuff() method, and then later on BaseClass was changed to add a DoStuff() method, (remember that they may be written by different people and exist in different assemblies) then a ban on member hiding would have suddenly made DerivedClass buggy without it changing. Also, if the new DoStuff() on BaseClass was virtual, then automatically making that on DerivedClass 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 use new to make it clear we definitely want to hide, but leaving it out hides and emits a warning on compilation).

  2. Poor-man's covariance. Consider a Clone() method on BaseClass that returns a new BaseClass that's a copy of that created. In the override on DerivedClass this will create a DerivedClass but return it as a BaseClass, which isn't as useful. What we could do is to have a virtual protected CreateClone() that is overridden. In BaseClass we have a Clone() that returns the result of this - and all is well - in DerivedClass we hide this with a new Clone() that returns a DerivedClass. Calling Clone() on BaseClass will always return a BaseClass reference, which will be a BaseClass value or a DerivedClass value as appropriate. Calling Clone() on DerivedClass will return a DerivedClass 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆