【问题标题】:Override Keyword in C#覆盖 C# 中的关键字
【发布时间】:2015-04-02 06:43:42
【问题描述】:

我有以下课程:

namespace ConsoleApplication8
{
    public abstract class Employee
    {
        public virtual void Show()
        {
            Console.WriteLine("from base.");
        }
    }

    public class Manager:Employee 
    {
        public void Show()
        {

            Console.WriteLine("from child.");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var man=new Manager();
            man.Show();
            Console.ReadKey();
        }
    }
}

这里我没有在派生类Manager 中为方法Show() 使用任何override 关键字,但代码运行正常。那么override关键字的实际用途是什么。

【问题讨论】:

  • 尝试员工 man = new Manager();和经理人 = 新经理();有和没有覆盖而不是 var man = new Manager();看看你是否还有问题。
  • 这里的重点是compile-time中如何定义变量。当它已经被引用为Manager(在您的情况下使用var)时,编译器知道调用Manager.Show。当您将 man 称为基本类型 (Employee) 时,多态性 开始发挥作用,现在 virtual 关键字告诉编译器在 runtime 中检查可能的重写方法i>(通常使用 vTable en.wikipedia.org/wiki/Virtual_method_table)。

标签: c#


【解决方案1】:

你没有覆盖原来的方法,你是hiding它。这也是可能的,但可能不是您想要的或您期望的,因为您失去了polymorphism。我举个例子:

static void Main(string[] args)
{
    var man=new Manager();
    man.Show();
    Console.ReadKey();
}

这是您的代码并输出“来自孩子”。以下,当使用“覆盖”时,也会输出“来自孩子”。在你的情况下不会。

static void Main(string[] args)
{
    var man=new Manager();
    (man as Employee).Show();
    Console.ReadKey();
}

这里提出了类似的问题:virtual keyword in c#。虽然它没有解决override 关键字,但问题类别大致相同。


多态性何时有用的真实示例。我必须编写一个应用程序来根据他们的角色计算公司中所有员工的奖金。正如您所做的那样,我有一个带有 public virtual double CalculateBonus(); 方法的员工类和几个派生自该方法的类。

由于多态性,我所要做的就是迭代所有员工的 List<Employee>,无论他们的角色如何,并调用 CalculateBonus 方法,因为多态性确保始终调用覆盖。

如果没有覆盖,奖金将全部为 0,因为这是 CalculateBonus 在类 Employee 中的默认结果。

【讨论】:

  • @haim770 - 他在技术意义上使用hiding
  • Pssh 实现/子类型覆盖。永远的接口(和显式实现)!
  • @user2864740 并在每个类中重新实现共享功能...?
  • @ThorstenDittmar SRP 和 DI。虽然我不会说“永远没有用”(由于固有的树结构,UI 库是一个相当好的反例),但我相信大多数代码应该具有非常低的子类型与组件的比率,保持它特殊情况(和学校讲座)。除了普遍不喜欢实现子类型之外,我认为这对于问题的范围来说是一个相当好的答案 - 但硬币的“另一面”(接口)以及如何与 [虚拟] 方法和多态性相适应通常被回避。
【解决方案2】:

https://msdn.microsoft.com/en-us/library/ebca9ah3.aspx https://msdn.microsoft.com/en-us/library/ms173153.aspx

您将隐藏底层方法,因此您可能会收到关于它的编译器警告并结合使用“new”关键字来隐藏底层成员。覆盖很简单——你用自己的实现“覆盖”底层实现细节

【讨论】:

    【解决方案3】:

    检查差异

    void Main()
    {
        Person instance1=new SpecificPerson();
        instance1.Execute();//Person
    
        SpecificPerson instance2=new SpecificPerson();
        instance2.Execute();//Specific
    }
    
        public class Person
        {
            public virtual void Execute()
            {
                Console.WriteLine("Person");
            }
        }
    
        public class SpecificPerson:Person
        {
            public void Execute()
            {
                Console.WriteLine("Specific");
            }
        }
    

    Overriding vs method hiding

    【讨论】:

    • 不显示virtual 方法或override 应用。确保链接回原始问题/代码。
    • 那么如果/当使用override 会发生什么?
    • @user2864740 在这两种情况下你都会得到特定的
    • 那么什么时候/为什么应该使用override,它有什么作用而不是不指定它?
    • @user2864740 应该在你想要覆盖的时候使用覆盖。请参阅我为您写的真实示例的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-30
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 2023-03-07
    • 1970-01-01
    相关资源
    最近更新 更多