虚拟关键字调用方法的大多数派生定义
本文关键字:大多数 派生 定义 方法 关键字 调用 虚拟 | 更新日期: 2023-09-27 18:29:31
我在读这篇文章覆盖与方法隐藏
我读到"..当在对象上调用虚拟方法时,该方法的最派生版本被称为"
但是当我执行以下代码时:
class A
{
public virtual void print()
{
Console.WriteLine("A called");
Console.Read();
}
}
class B :A
{
public override void print()
{
Console.WriteLine("B called");
Console.Read();
}
}
class C : B
{
public override void print()
{
Console.WriteLine("C called");
Console.Read();
}
}
static void Main(string[] args)
{
B b = new B();
b.print(); it prints B?
}
它打印B。如果上面引用的说法是真的,它不应该是"C"吗?我错过了什么?在这种情况下,"最派生"是什么意思?
它将从调用它的实例的类型调用方法,您使用类B
的实例来调用它,因此B
的实现将被调用,如果您使用的是类C
的实例,则C
类的重写实现将被调用。
例如:
class B :A
{
public override void print()
{
Console.WriteLine("B called");
Console.Read();
}
public virtual void printfromB()
{
Console.WriteLine("printfromB in B called");
Console.Read();
}
}
class C : B
{
public override void print()
{
Console.WriteLine("C called");
Console.Read();
}
public override void printfromB()
{
Console.WriteLine("printfromB in C called");
Console.Read();
}
}
现在,如果你这样称呼它:
static void Main(string[] args)
{
A a = new C();
a.print(); // it prints C (most derived implementation called)
B b = new C();
b.printfromB(); // it prints "printfromB in C called"
}
B
时,不可能调用C
。
最初的"最派生"术语可以使用以下内容来理解:
A data = new C();
data.print();
即使编译器将data
视为A
,也会调用最派生的版本(不是A.print
或B.print
,而是C.print
)(这是因为方法是virtual
)。
参见多态性
我认为你对答案中单词的技术性感到困惑。
这里有两件事,
- 在被实例化的派生类的上下文中方法的大多数派生版本
如果你这样做了,
A a = new B();
a. print(); // this will invoke the method on the class B,
// since instance of class A has reference to instance of B.
如果您执行以下操作:
A a = new C();
a. print(); // Should call the method on class C, since base class has reference to to the instance of C.
同样,一种更直观的表达方式是:
A a = new A();
a.print(); // this will call the method print in class A irrespective of whether this method was overriden in one of the derived classes.
这是动态多态性的前提,其中,客户端可以对A的基类对象调用方法print()而不需要知道A是否引用了B或C。行为在客户端代码中动态变化。
- 或者,您也可以通过以下方式思考大多数派生版本:
假设方法print()在C中没有被覆盖,但在B中被覆盖,那么print()的最派生版本将在类B中。下面的snip应该会有所帮助。
class A
{
public virtual void print()
{
Console.WriteLine("A called");
Console.Read();
}
}
class B :A
{
public override void print()
{
Console.WriteLine("B called");
Console.Read();
}
}
class C : B
{
public void somerandommethod()
{
// some random method not really relevant to this example.
}
}
static void Main(string[] args)
{
A a = new C();
a.print(); // it will now print B (since B has the most derived implementation of print())
}
希望这个答案能有所帮助。
最好。