为什么方法重写是运行时绑定的

本文关键字:绑定 运行时 方法 重写 为什么 | 更新日期: 2023-09-27 17:58:08

Overriding是一个允许您更改子类中方法功能的原则。

例如

//Overriding
public class test
{
        public virtual getStuff(int id)
        {
            //Get stuff default location
        }
}
public class test2 : test
{
        public override getStuff(int id)
        {
            //base.getStuff(id);
            //or - Get stuff new location
        }
}

当我们在test2中Inherit测试类时,编译器知道父类中有一个虚拟方法。那么,为什么方法重写是运行时绑定的而不是编译时绑定的呢?

为什么方法重写是运行时绑定的

它是运行时绑定(如果这是正确的措辞——我不相信),因为即使有test2变量,你实际上也可以有:

test2 obj = new test3(); // imagine test3 inherits from test2
obj.getStuff(id);

这里的变量test2,但对象是test3。您可能会争辩说,如果是sealed等,但实际上即使是非虚拟实例(非静态)方法也要经过callvirt过程。它运行良好,速度非常快。此外,callvirt操作码有必要的null检查,这意味着你的代码不必(在引擎盖下)不断地检查null(如果是静态调用,这是必要的)

这里唯一的例外是覆盖object方法的struct;以下是静态调用:

int i = 1;
string s = i.ToString();
class BaseClass
{
   public virtual void Test(){
      Console.WriteLine("This is test of base class");
   }
}
class DerivedClass : BaseClass
{
   public override void Test(){
      Console.WriteLine("This is test of derived class");
   }
}
class DerivedClass1 : BaseClass
{
   public override void Test(){
      Console.WriteLine("This is test of derived class-1");
   }
}

现在如果你使用

BaseClass b = new DerivedClass();
b.Test(); // This will derived class method

假设由另一种方法创建的对象取决于条件,但所有对象都是从BaseClass 派生的

public BaseClass GetObject(int i)
{
    if(i==1) return new DerivedClass();
    if(i==2) return new DerivedClass1();
}
BaseClass b = GetObject(1);
b.Test(); // This will derivedclass method
BaseClass b = GetObject(2);
b.Test(); // This will derivedclass1 method

所以所有的事情都取决于i的值,它可以在运行时决定,而在运行时取决于根据测试方法调用保持的引用b的类型。

考虑一下这个片段。

test Create()
{
    return new test2();
}
test a = Create();
a.getStuff(0); // which method is called?

编译器无法知道Create方法的返回值是test2类型。它是明确隐藏的。

您应该从编译器的角度来看待这个问题。假设编译器将该值视为test类型,那么它怎么知道调用test2.getStuff方法呢?

只需添加到其他答案中,编译器在编译时无法解决的任何问题,都可以通过在运行时发出适当的代码或使用其他技术来实现。