c#中的方法重写

本文关键字:重写 方法 | 更新日期: 2023-09-27 18:02:12

考虑到以下内容:

class BC
{
  public void Display()
  {
     System.Console.WriteLine("BC::Display");
  }
}
class DC : BC
{
  new public void Display()
  {
     System.Console.WriteLine("DC::Display");
  }
}
class Demo
{
  public static void Main()
  {
     BC b;
     b = new BC();
     b.Display();    
     b = new DC();
     b.Display();    
  }
}

我理解以下代码调用基类Display()方法:

BC b;
b = new BC();
b.Display();  

下面几行调用派生类Display(),通过使用new关键字隐藏基类实现:

b = new DC();
b.Display(); 

我想知道new关键字在内部做什么。

这段代码的源代码包括以下解释:

由于b包含对DC类型对象的引用,因此可以期望执行DC类的Display()函数。但这并没有发生。取而代之的是BC类的Display()。这是因为函数是根据引用的类型调用的,而不是根据引用变量b所引用的类型调用的。由于b是BC类型的引用,因此无论b引用的是谁,都会调用BC类的Display()函数。

我对这个特殊的位感到非常困惑:"因为函数是基于引用的类型调用的,而不是引用变量b引用的内容"

这里的"函数是基于引用的类型调用的"是什么意思

b = new DC();
b.Display();  

这里的b是什么类型?它被声明为类BC的实例名但是后来b变成了DC类的实例

c#中的方法重写

你所做的不是覆盖,而是遮蔽。new关键字允许您在BCDC类中都有Display方法,但是这些方法根本不相关,它们只是具有相同的名称。

要覆盖该方法,您需要为BC类中的方法使用virtual关键字,并在DC类中使用overrides方法。

当你遮蔽一个方法时,是引用的类型决定了使用哪个方法:

BC b1;
b1 = new BC();
b1.Display(); // Calls the method in BC
BC b2;
b2 = new DC();
b2.Display(); // Calls the method in BC
DC d1;
d1 = new DC();
d1.Display(); // Calls the method in DC

重写方法如下:

class BC {
  public virtual void Display() {
    System.Console.WriteLine("BC::Display");
  }
}
class DC : BC {
  override public void Display() {
    System.Console.WriteLine("DC::Display");
  }
}

当重写方法时,方法是相关的,并且是对象的实际类型决定使用哪个方法,而不是引用的类型:

BC b1;
b1 = new BC();
b1.Display(); // Calls the method in BC
BC b2;
b2 = new DC();
b2.Display(); // Calls the method in DC
DC d1;
d1 = new DC();
d1.Display(); // Calls the method in DC

重写和隐藏之间的另一个区别是,当你隐藏一个方法时,它们不必完全相似,new关键字只是告诉编译器你想在基类之外的其他地方重用标识符。当重写一个方法时,方法签名必须是相同的。

例如,你可以将一个接受string的公共方法隐藏为完全不同的东西,比如int类型的私有属性:

public class X {
  public void XX(string z) { }
}
public class Y : X {
  private new int XX { get; set; }
}
X x = new Y();
x.XX();
Y y = new Y();
y.XX = 42;

我想知道新的关键字在内部做什么。

你不是一个人。请看这个问题的答案:

关于virtual/new/override的混淆

和接下来的问题:

更多关于Virtual/new…+接口!

关于如何实现虚拟、新建、覆盖和接口实现的详细但仍然高层次的解释。

Display设置为BC中的虚函数,并在DC中重写,然后它将按您期望的方式工作