之前我问了一个没有完全回答的问题,因此我决定重新表述我的问题以了解发生了什么:
这是我的类层次结构:
interface I
{
void f();
}
class A : I
{
// non virtual method
public void f()
{
Debug.Log("---->> A ");
}
}
class B : A
{
// non overriding but hiding class A method
public void f()
{
Debug.Log("---->> B ");
}
}
class C : I
{
// non virtual method
public void f()
{
Debug.Log("---->> C ");
}
}
执行代码如下:
Random rnd = new Random();
var randomI = rnd.Next(0, 2);
I i = null;
if (randomI == 0)
{
i = new B();
}
else
{
i = new C();
}
i.f();
就目前而言,它会输出 A 或 C。它不会输出 B。
这里的问题是:您能否通过涵盖这些步骤来解释如何决定调用哪些函数?
- 何时决定调用哪个函数 - 运行时还是编译时?
- 决定调用什么函数的机制是什么?
最佳答案
在编译时它会调用I
接口(interface),然后在运行时它会调用继承链中实现I.f()
的顶级方法。
所以,在你的代码中这个
A a = new A();
a.f();
B b = new B();
b.f();
将使编译器执行以下指令:
- 创建类 A 的实例并分配给“a”
- 获取分配给“a”的对象并调用位于继承链顶部并实现A.f() 的方法。在这种情况下是 A.f() 本身
- 创建B类实例并赋值
- 获取分配给“a”的对象并调用位于继承链顶部并实现B.f() 的方法。在这种情况下是 B.f() 本身
结果为“A”和“B”。
但是,当你这样做时:
I i;
i = new B();
i.f();
你让它编译以下指令:
- 声明一个变量“i”
- 创建一个新的对象 B 并将其赋值给“i”
- 获取分配给“i”的对象并调用位于继承链顶部并实现I.f() 的方法。是A.f(),因为类
B
没有实现接口(interface)I
在 i.f()
行,它不知道 new B()
被分配给 i
,它可能是从某个地方传递的别的。它只知道有一些抽象对象实例实现了 I
并且它需要调用它的 f()
方法。
您可以将新
方法视为具有不同名称 的方法:
public class B : A
{
// non overriding but hiding class A method
public void anotherName()
{
Debug.Log("---->> B ");
}
}
A a = new A();
a.f();
B b = new B();
b.anotherName();
I i = new B();
i.f(); // this will obviously call the `A.f()` because there is no such method in B
唯一的区别是您不能为继承的类实例调用隐藏方法。
关于c# - 会调用什么函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52204649/