【问题标题】:Why does not call parent method when we don't use method hiding?为什么不使用方法隐藏时不调用父方法?
【发布时间】:2013-07-27 16:53:39
【问题描述】:

考虑这段代码:

internal class Program
   {

      private static void Main(string[] args)
         {
            var student = new Student();
            student.ShowInfo(); //output --> "I am Student"
        }
    }
    public class Person
    {
        public void ShowInfo()
        {
            Console.WriteLine("I am person");
        }
    }

    public class Student : Person
    {
        public void ShowInfo()
        {
            Console.WriteLine("I am Student");
        }
    }

在上面的代码中我们没有使用方法隐藏。

当创建学生实例并调用showinfo 方法时,我的输出是I am Student 我不使用new 关键字。

不使用方法隐藏为什么不调用父方法?

【问题讨论】:

  • 据我所知,一定有ambiguity error
  • 默认方法是隐藏的,即使你使用new或不使用
  • var 这里和Student一样,所以你的代码是Student student = new Student();。你为什么期望student.ShowInfo 使用Person.ShowInfo?这将如何运作?
  • @Kobi 确切地说它在 Java 或 Python 或任何其他默认方法是虚拟的语言中是如何工作的 - 或者更确切地说,方法隐藏不是默认的,甚至不是语言功能。这是一种 C++ 主义/C# 主义,但情况并非如此,反之亦然,但是对于 OO 语言,这两种选择都不是显而易见的
  • @millimoose - 除非我遗漏了什么,否则默认情况下虚拟意味着Person x = new Student(); x.ShowInfo() 将使用Student.ShowInfo。这很好,而且我个人更喜欢 Java 的方法而不是 C# 的方法。这里有Student x = new Student()

标签: c# method-hiding


【解决方案1】:

它使用方法隐藏,它只是隐式使用。 new 关键字应该用于明确表明您知道您正在隐藏该方法,但是,您的代码仍将编译并隐藏该方法。虽然这绝对不推荐。

【讨论】:

    【解决方案2】:

    Student.ShowInfo() 隐藏继承成员Person.ShowInfo()

    你最好检查编译器警告

    'ConsoleApplication5.Program.Student.ShowInfo()' 隐藏继承 成员'ConsoleApplication5.Program.Person.ShowInfo()'。使用新的 如果打算隐藏,则使用关键字。

    【讨论】:

      【解决方案3】:

      使用相同的方法签名ShowInfo 意味着您将隐藏父类方法。 new 关键字不是必需的,它只是让开发人员知道当前方法在父类中隐藏了另一个方法。

      【讨论】:

        【解决方案4】:

        无论您是否使用new 关键字,基本方法都不是虚拟的。所以它总是会被调用的派生方法。唯一的区别是编译器会向您发出警告,因为基本方法是隐藏的,并且您没有明确使用 new 关键字:

        'Student.ShowInfo()' 隐藏继承的成员'Person.ShowInfo()'。如果要隐藏,请使用 new 关键字。

        C# 编译器发出此消息是为了警告您,您可能在没有意识到的情况下错误地这样做了。

        为了修复警告,如果这种隐藏是故意的,您应该使用 new 关键字:

        public new void ShowInfo()
        {
            Console.WriteLine("I am Student");
        }
        

        如果没有,你应该将基础方法设为虚拟:

        public class Person
        {
            public virtual void ShowInfo()
            {
                Console.WriteLine("I am person");
            }
        }
        

        然后在派生类中覆盖它:

        public class Student : Person
        {
            public override void ShowInfo()
            {
                Console.WriteLine("I am Student");
            }
        }
        

        显然,在这两种情况下,您都可以根据需要调用基本方法:

        public override void ShowInfo()
        {
            base.ShowInfo();
            Console.WriteLine("I am Student");
        }
        

        【讨论】:

          【解决方案5】:

          这是隐藏,这就是为什么您会收到警告说如果您有意隐藏它,您应该使用 new 关键字。检查C# Language SpecHiding through inheritance3.7.1.2 部分。

          当类或结构发生时,通过继承隐藏名称 重新声明从基类继承的名称。 这种类型的名称隐藏采用以下形式之一:

          •A 类中引入的常量、字段、属性、事件或类型,或 struct 隐藏所有同名的基类成员。

          •一种方法 在类或结构中引入隐藏所有非方法基类 具有相同名称的成员,以及具有相同名称的所有基类方法 签名(方法名称和参数计数、修饰符和类型)。

          •类或结构中引入的索引器隐藏所有基类 具有相同签名(参数计数和类型)的索引器。

          【讨论】:

            【解决方案6】:

            原因是,当您重新声明基类方法时,它是隐藏的。它被称为hiding through inheritance

            【讨论】:

              【解决方案7】:

              实际上,从程序逻辑的角度来看,新的修饰符根本没有任何作用

              新修饰符的唯一作用是记录您的意图,以便:

              • 编译器可以在适当的时候警告你(例如在不隐藏继承成员的声明中使用 new 修饰符时 - 或者相反,即使声明确实隐藏了继承会员)

              • 其他开发人员更容易理解您的代码

              隐藏/不隐藏真正重要的是您是否使用override modifier(仅当继承的成员是虚拟的时才能使用)。如果不使用 override 修饰符,则继承的成员始终是隐藏的。在您的示例中,您没有使用 override 修饰符,因此您 do 隐藏了继承的成员。

              注意:不要混淆'new modifier' with the 'new operator' or the 'new constraint'

              【讨论】:

                【解决方案8】:

                正如其他人所说的method hiding is implicit,无论您是否使用了new 关键字。您可以检查这段代码 -

                     private static void Main(string[] args)
                     {
                        Person student = new Student();
                        student.ShowInfo(); //output --> "I am person"
                     }
                

                当你instantiate base class object with derived class,你的derived method won't get called

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2013-10-28
                  • 1970-01-01
                  • 2021-04-08
                  • 1970-01-01
                  • 2016-02-13
                  • 2015-07-01
                  • 2018-03-26
                  • 2011-07-19
                  相关资源
                  最近更新 更多