阅读 article & article - 我感到困惑。
它说:
如果层次结构的不同级别有两种方法,那么 即使不是“更好的功能”,也会首先选择“更深”的 会员“为电话。
另外 -
事实证明,如果你覆盖了孩子的基类方法 类,不算是声明它。
现在让我们回到我的问题:
<案例1 public class Base
{
public virtual void Foo(int x) { "1".Dump();}
}
public class Child : Base
{
public void Foo(object x) { "3".Dump();}
public override void Foo(int x) { "2".Dump();}
}
void Main()
{
Child c = new Child();
c.Foo(10); //emits 3
}
好的。根据文章
“更深”的人将首先被选中,即使它不是“更好的功能。它不计算覆盖......
所以它是正确的,程序发出“3”。 (Foo(object x)
已执行)
让我们更改第1行的顺序:
<案例2 public class Base
{
public virtual void Foo(int x) { "1".Dump();}
public void Foo(object x) { "3".Dump();} //<line being moved here
}
public class Child : Base
{
public override void Foo(int x) { "2".Dump();}
}
void Main()
{
Child c = new Child();
c.Foo(10); //emits 2 !!!!
}
现在发出“2”。
现在让我们将所有 int更改为object ,将所有对象更改为int :
<案例3 public class Base
{
public virtual void Foo(object x) { "1".Dump();}
public void Foo(int x) { "3".Dump();}
}
public class Child : Base
{
public override void Foo(object x) { "2".Dump();}
}
void Main()
{
Child c = new Child();
c.Foo(1); //emits "3"
}
问题:
问题#1:在案例2中,Child
从父亲那里继承了Foo(object x)
并且他也覆盖了一个方法。
但我们只是这么说:
事实证明,如果你覆盖了孩子的基类方法 类,不算是声明它
???
事实上,在这种情况下,我们还没有宣布继承的功能......所以这里的规则是什么?
问题2:在案例3中,Child
从父亲那里继承了Foo(int x)
并且他也覆盖了一个方法。
但现在,他选择了父亲的职能......
似乎override
只有在完全匹配时才会获胜。
再次,在这种情况下这里有什么规则?
答案 0 :(得分:3)
在类型T中查看名称N的member lookup process(在您的案例成员Foo
中,类型为Child
):
首先,在T中声明的所有可访问(第3.5节)成员的集合以及T的基本类型(第7.3.1节)构造:
virtual void Foo(int x) // Base
void Foo(object x) // Base
override void Foo(int x) // Child
从集合中排除包含覆盖修饰符的声明。
virtual void Foo(int x) // Base
void Foo(object x) // Base
Argument有一个整数类型。所以,这里最好的选择是(参数类型匹配参数类型)
virtual void Foo(int x) // Base
这个方法叫做。但它是虚方法。由于virtual method invocation机制而调用它:
对于在类中声明或继承的每个虚方法,都存在 存在关于方法的最派生的实现 那个班。虚拟方法M的最多派生实现 对R类的尊重如下确定:
- 如果R包含M的引入虚拟声明,那么这是M的最多派生实现。
- 否则,如果R包含M的覆盖,则这是M的最多派生实现。
- 否则,关于R的M的最派生实现与关于的M的最派生实现相同 R的直接基类。
关于类virtual void Foo(int x)
,Child
方法的派生最多的实现是什么?是的,它是
override void Foo(int x) // Child
调用哪个。 第三个样本中应用了相同的规则。但是当重写方法删除后剩下两个选项时,最佳选择(由于参数类型)是非虚方法。
答案 1 :(得分:3)
发生了两件事:
所以基本上查找规则可以选择采用int的方法,如果它在更深的类上,但是当方法被调用时,如果它被覆盖,它将调用该方法在子类上采用int。
答案 2 :(得分:1)
我认为你只是通过阅读这两篇文章弄乱你的事实..它应该像任何其他正常的重写函数一样,因为在子类中没有重载,因此没有什么可供选择。让我们看看简单的例子:
public class A
{
public virtual void Foo()
{
Console.WriteLine("A.Foo() called");
}
}
public class B: A
{
public override void Foo()
{
Console.WriteLine("B.Foo() called");
}
}
void Main()
{
new B().Foo();
}
预期产量是多少?显然没有想过任何人会说B.Foo()叫。在你的情况下,同样的事情正在发生。基类有一个更好的重载方法并不重要,子类只是赢了它..不要过于复杂的东西..
关于案例3,我不完全确定这个,但这里发生的是编译器尝试隐式转换为对象,然后它发现有一个更深层次的方法具有相同的签名,因此规则
如果层次结构的不同级别有两种方法,那么 即使不是“更好的功能”,也会首先选择“更深”的 会员“为电话
现在一旦进入基类,它就注意到有一个更好的方法可以使用,因此调用该方法..
P.S:上述解释是基于已经观察到的结果,可能不一定是上述行为的确切原因。