【问题标题】:Inheritance and the new keyword继承和新关键字
【发布时间】:2014-02-27 08:33:41
【问题描述】:

当我添加新关键字或删除内容时,行为方式相同! new 关键字应该是重新实现基类的方法并将其隐藏,这是示例:

class Program
    {
        static void Main(string[] args)
        {
            BaseClass bc = new BaseClass();
            DerivedClass dc = new DerivedClass();
            BaseClass bcdc = new DerivedClass();

            Console.WriteLine("bc __________________");
            bc.Method1();
            bc.Method2();
            Console.WriteLine("dc __________________");
            dc.Method1();
            dc.Method2();
            Console.WriteLine("bcdc __________________");
            bcdc.Method1();
            bcdc.Method2();

            Console.ReadLine();
        }
    }

    class BaseClass
    {
        public void Method1()
        {
            Console.WriteLine("Base - Method1");
        }
        public void Method2()
        {
            Console.WriteLine("Base - Method2");
        }
    }

    class DerivedClass : BaseClass
    {
        public new void Method1()
        {
            Console.WriteLine("Derived - Method1");
        }
        public void Method2()
        {
            Console.WriteLine("Derived - Method2");
        }
    }

bcdc 的输出将显示 基础 - 方法 1 调用 bcdc.Method1() 时;它不应该显示“Derived - Method1”吗,如果不是这样,请向我解释原因。 (当使用 Virtual/override 时,它​​工作得很好,我很满意)但是使用 new 关键字,无论有没有它,它都可以正常工作。

【问题讨论】:

    标签: c# .net inheritance overriding new-operator


    【解决方案1】:

    查看C# Language Specification,第 56 页:

    声明在声明所属的声明空间中定义了一个名称。除了重载成员(第 3.6 节)外,如果有两个或多个声明在声明空间中引入同名成员,则属于编译时错误。

    当您将变量声明为特定类型时,成员查找是使用该类型的声明空间完成的,但被覆盖的成员除外。由于您没有覆盖Method1 成员,因此会发现并使用基类的成员。

    【讨论】:

      【解决方案2】:

      嗯,这正是virtual/overridenew 之间的区别!

      • 在第一种情况下 (virtual/override),将调用被覆盖的方法,而不管您从中调用它的变量类型如何。这种行为有一个名称,称为多态性,它广泛用于面向对象的编程中。
      • 在第二种情况下(new),这取决于!如果变量是在定义new 方法之前的类型,那么当您从该变量调用时会调用旧方法。否则,调用较新的方法。这称为 method shadowing(这些方法具有相同的名称,但它们实际上是不同的并且可能不相关 - 这就是您获得不同行为的原因)并且当基类引入了您的派生的新方法时使用它类已经有了那个方法。要告诉 C# 他们的关系不是virtual/override,你使用new。通常最好避免这种情况。

      【讨论】:

      • 我的问题是是否添加新的会调用基类的Method1,如果新关键字没有改变,我找不到Otherwise, the newer method is called在哪里,那为什么会在这里?
      • dc.Method1() 应该打印Derived,因为dc 变量的类型是DerivedClassbcdc.Method1() 应该打印Base,因为bcdc 变量的类型是BaseClass
      【解决方案3】:

      使用new keyword 只会隐藏基本实现,它不会覆盖它。不使用 new 修饰符会做同样的事情,但是是隐式的。

      当您将变量定义为BaseClass 时,是否将其初始化为派生变量并不重要。您仍然只能访问在基类中定义的方法。

      BaseClass bcdc = new DerivedClass();
      
      Console.WriteLine("bcdc __________________");
      bcdc.Method1();
      bcdc.Method2();
      

      同样,使用new 访问修饰符不会改变功能,它只是为查看类实现的人提供了一个线索,以了解该方法应该隐藏基本实现。

      【讨论】:

      • 你没听懂我的意思,我在问为什么放新的操作符什么都没有改变
      • 我不知道为什么这被否决了。据我所知,它非常准确。我会给它+1。
      • 这可能是我最初对问题的误解。我原本以为 OP 想知道为什么使用 new 没有覆盖基本实现。
      • 当你隐藏一个方法而不使用 new 关键字时,也会产生编译器警告。
      • @AymenDaoudi 无论您是否使用new 修饰符,都会调用基本方法not。你的说法“它没有隐藏基类”方法,它实际上仍然被调用”是不正确的。有或没有 new 修饰符实际上没有功能差异。
      【解决方案4】:

      在某些方面newvirtual/override 是相反的关键字。

      • virtual / override: 用于在继承层次结构中声明具有跨多种类型的单一实现的单一方法
      • new:用于显式声明一个新方法,该方法与具有相同签名的所有其他方法分开。没有new 具有相同的效果,它只是隐含的

      在这种情况下,代码没有virtual 方法,因此编译器静态绑定到由调用它的引用类型指定的方法

      【讨论】:

      • 如果我理解你的第二点,新关键字无论是否存在都没有影响,对吗?如果是,它为什么存在?如果不是,请向我解释一下,并给我一个例子,其中 new 工作就像覆盖并使派生类的方法 1 称为
      • @AymenDaoudi new 关键字是可选的,只是用于使方法隐藏声明性与隐式。它绝不像override 那样工作,所以很难举个例子 htat 让它看起来像它
      猜你喜欢
      • 2012-09-21
      • 2015-12-04
      • 1970-01-01
      • 1970-01-01
      • 2011-12-11
      • 1970-01-01
      • 2012-12-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多