将调用什么功能?

Nar*_*rek 9 c# interface

以前我问过一个问题没有得到充分回答,因此我决定重新制定我的问题以了解发生了什么:

这是我的类层次结构:

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 ");
    }
}
Run Code Online (Sandbox Code Playgroud)

这是执行代码:

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(); 
Run Code Online (Sandbox Code Playgroud)

就像现在一样,它将输出A或C.它不会输出B.

这是一个问题:您能解释一下如何通过涵盖这些步骤来决定调用哪个函数?

  1. 当决定调用什么函数 - 运行时或编译时?
  2. 如何决定调用哪个函数的机制是什么?

Yel*_*yev 4

在编译时,它绑定对I接口的调用,然后在运行时,它调用继承链中实现I.f().

所以,在你的代码中

A a = new A();
a.f();

B b = new B();
b.f();
Run Code Online (Sandbox Code Playgroud)

将使编译器执行以下指令:

  • 创建类 A 的实例并分配给“a”
  • 获取分配给“a”的对象并调用该方法,该方法位于继承链的顶部并实现Af()。在这种情况下它是 Af() 本身
  • 创建B类的实例并赋值
  • 获取分配给“a”的对象并调用该方法,该方法位于继承链的顶部并实现Bf()。在这种情况下是 Bf() 本身

结果是“A”和“B”。

然而,当你这样做时:

I i;
i = new B();
i.f();
Run Code Online (Sandbox Code Playgroud)

你让它编译以下指令:

  • 声明一个变量“i”
  • 创建一个新对象 B 并将其分配给“i”
  • 获取分配给“i”的对象并调用该方法,该方法位于继承链的顶部并实现If()。是Af(),因为类B没有实现接口I

在该i.f()行中,它不知道new B()已分配给i,它可以从其他地方传递。它只知道有一些实现的抽象对象实例,I并且需要调用它的f()方法。

您可以想到具有不同名称new的方法之类的方法:

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
Run Code Online (Sandbox Code Playgroud)

唯一的区别是您不能为继承的类实例调用隐藏方法。