[英]class casting in c#
这是C#代码
class A {
public int Foo(){ return 5;}
public virtual int Bar(){return 5;}
}
class B : A{
public new int Foo() { return 1;} //shadow
public override int Bar() {return 1;} //override
}
输出
Console.WriteLine(((A)clB).Foo()); // output 5 <<<--
Console.WriteLine(((A)clB).Bar()); // output 1
我们如何获得这个输出。任何人都可以在这里解释类转换过程。
更新:
以及这如何显示阴影和替代之间的区别
我假设
var clB = new B();
Foo
和Bar
方法之间的区别在于,尽管Bar
使用继承和多态性来决定要调用的实现,但是Foo
方法隐藏了其原始实现。
A.Foo()
, A.Foo()
和B.Foo()
完全无关,它们恰好具有相同的名称。 当编译器看到类型A
的变量调用Foo
它将进入并执行A.Foo()
,因为该方法不是虚拟的,因此无法覆盖它。 类似地,当看到调用Foo
B
类型的变量时,它将执行B.Foo()
,而不管该变量中包含的实例的实际类型如何。
另一方面, Bar
方法被定义为虚拟方法,并且继承的类可以(并且应该)重写其实现。 因此,无论何时调用Bar
,无论它来自声明为A
或B
的变量,都必须在调用对象本身的层次结构中将实际调用的方法作为“最新”实现来查找。来自用于引用对象的变量类型的影响。
在类B
,您将引入一个new
方法Foo
,其名称和签名与已有方法相同(从A
继承)。 因此, B
有两个同名方法。 如果可以避免,那不是您要做的事情。
Foo
被调用的两种方法中的哪一种取决于所使用的变量或表达式(类型A
或B
)的编译时类型。
相反,方法Bar
是virtual
。 B
只有一种方法Bar
。 无论表达式的编译时类型是什么,总是会调用“正确”的覆盖。
写作
((A)clB).Foo()
就像说“对待clB
好像它是一个A
(如果可以)并给我Foo()
的结果”一样。 由于A
具有非虚拟Foo
方法,因此它将执行A.Foo
。 由于B
的Foo
方法是“ new
”方法,因此在这种情况下不使用它。
写作
((A)clB).Bar()
相似-“将clB
当作A
对待(如果可以的话),然后给我Bar()
的结果”。 现在A
具有虚拟的 Bar
方法,这意味着可以在基类中覆盖它。 由于该对象实际上是B
,它具有Foo()
的override
, B.Foo()
将改为调用B.Foo()
。
var clB = new B();
//Uses B's Foo method
Console.WriteLine(clB.Foo()); // output 1
//Uses A's Foo method since new was use to overload method
Console.WriteLine(((A)clB).Foo()); // output 5
//Uses B's Bar Method
Console.WriteLine(clB.Bar()); // output 1
//Uses B's Bar Method since A's Bar method was virtual
Console.WriteLine(((A)clB).Bar()); // output 1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.