假设类A继承自类B,而类B又继承自类C。现在假设在A中定义了一个虚方法void f(),同时B和C都重写了该方法。在A的任何方法中调用B.f()只需使用base.f()即可完成。那么,在A的方法中如何调用C.f()呢?
通常情况下,通过覆盖一个类(overriding a class),您接受它提供的接口和一些所需的行为。A 不应该知道它的超级父类(super-superclass)的存在,除非在它的父类中以某种方式被显式地暴露。这实际上是可取的,因为当您子类化 B 时,您不需要知道 C 的实现方式。您甚至不应该知道 C 的存在。
如果 b 的 f() 调用了 base.f(),那么 a 的 base.f() 只需要调用自己的 base.f() 就完成了。如果没有,那么你自己唯一的方法就是通过基于反射的侵入式方法来实现。如果您发现自己需要这样做,则可能在设计上出现了错误(例如违反 Demeter 定律等)。
我猜您的意思是从C中的一个方法调用A.f()?
简短回答:您不能这样做
不过,如果您控制B,您可以添加一个方法到B中来显式地调用它的基类:
protected void BaseF()
{
base.f();
}
然后从 C 中调用该方法
这可以通过反射来实现。您可以获取当前类的类型,使用它来获取父类型,然后获取父类型的父类型。
之所以语言本身不直接支持此功能,是因为它破坏了继承的抽象模型。它与传统的面向对象设计并不兼容。
试试这个:
C c = this;
c.f();
这将打印出"C":
public static void Main()
{
A o = new A();
Console.WriteLine(o.f());
}
class C
{
public virtual string f()
{
return "C";
}
}
class B : C
{
public virtual string f()
{
return "B";
}
}
class A : B
{
public virtual string f()
{
C c = this;
return c.f();
}
}
public class C : B {
public override f() {
((A) this).f();
}
}
使用new
而不是override
是一种方法(函数不需要是虚拟的即可使用new
,尽管它可以是)。
但这可能会带来其他问题。如果在任何地方将MyClass
向上转换为MyBaseClass
,它将使用MyBaseClass
版本的函数。
private void Form1_Load(object sender, EventArgs e)
{
var mc = new MyClass();
mc.Foo();
((MyBaseClass) mc).Foo();
}
public class MyBaseClass
{
public virtual void Foo ()
{
Console.WriteLine("Calling from MyBaseClass");
}
}
public class MyClass : MyBaseClass
{
new public void Foo ()
{
Console.WriteLine("Calling from MyClass");
}
}
你所得到的输出为:
Calling from MyClass
Calling from MyBaseClass
class Program
{
static void Main(string[] args)
{
C c = new C();
A a = new A();
a.DoThis();
Console.ReadKey();
}
}
public class C
{
public virtual void DoThis() {
Console.WriteLine("In C"); }
}
public class B : C
{
public new void DoThis()
{
Console.WriteLine("In B");
}
}
public class A : B
{
public new void DoThis()
{
Console.WriteLine("In A..");
((C) this).DoThis();
}
}
这似乎是一个设计问题。
你有几个选择:
this
强制转换为C吗?((C)this).f(); - Michael Stum