我知道非虚拟方法是静态绑定的,据我所知,这意味着它在编译时本身就知道将在哪个对象上调用哪个方法。该决定是根据对象的静态类型做出的。让我感到困惑的是接口(而不是class)和静态绑定。
考虑这段代码,
public interface IA
{
void f();
}
public class A : IA
{
public void f() { Console.WriteLine("A.f()"); }
}
public class B : A
{
public new void f() { Console.WriteLine("B.f()"); }
}
B b = new B();
b.f(); //calls B.f() //Line 1
IA ia = b as IA;
ia.f(); //calls A.f() //Line 2
演示代码:http: //ideone.com/JOVmi
我明白了Line 1
。编译器可以知道b.f()
将调用它,B.f()
因为它知道它的静态类型b
是B
.
但是编译器如何在编译时自己决定ia.f()
调用A.f()
? 什么是对象的静态类型ia
?不是IA
吗?但那是一个接口,并且没有任何f()
. 那么它是如何工作的呢?
为了使案例更令人费解,让我们考虑这种static
方法:
static void g(IA ia)
{
ia.f(); //What will it call? There can be too many classes implementing IA!
}
正如评论所说,实现接口的类可能太多IA
,那么编译如何静态决定ia.f()
调用哪个方法?我的意思是,假设我有一个类定义为:
public class C : A, IA
{
public new void f() { Console.WriteLine("C.f()"); }
}
如您所见,C
与 不同,除了派生于 之外,还B
实现了. 这意味着,我们在这里有不同的行为:IA
A
g(new B()); //inside g(): ia.f() calls A.f() as before!
g(new C()); //inside g(): ia.f() doesn't calls A.f(), rather it calls C.f()
演示代码:http: //ideone.com/awCor
我如何理解所有这些变化,尤其是接口和静态绑定如何协同工作?
还有更多(ideone):
C c = new C();
c.f(); //calls C.f()
IA ia = c as IA;
ia.f(); //calls C.f()
A a = c as A;
a.f(); //doesn't call C.f() - instead calls A.f()
IA iaa = a as IA;
iaa.f(); //calls C.f() - not A.f()
请帮助我理解所有这些,以及 C# 编译器如何完成静态绑定。