假设A类继承自B类,而B继承自C类。现在假设在A中定义了一个虚方法void f(),它在B和C中都被重写。从任何一个调用Bf() A中的方法可以通过简单地使用base.f()来完成。如何从A?
中的方法调用C.f()答案 0 :(得分:11)
通常,通过重写一个类,您接受它提供了所需的接口和一些行为。 A不应该知道它的超级超级,除非它的超类以某种方式明确暴露。这实际上是可取的,因为当您继承B时,您不需要知道C是如何实现的。您甚至不应该知道C涉及。
如果b的f()调用base.f(),则base.f()只需要调用自己的base.f()就可以了。如果没有,那么自己做的唯一方法就是通过基于Reflection的侵入式方法。如果你发现自己需要这样做,你的设计可能会出错(违反了得墨忒耳定律)。
答案 1 :(得分:3)
您可以通过反思或IL代码生成。除此之外,你不能,你真的不应该,这听起来不像是好的设计。
当您在OOP中覆盖方法时,基本上说“对于这种类型,此方法将替换旧方法”,并且必要时(通常是)可以调用替换(覆盖)方法。
但是,你不能直接跳过一个关卡,除非你采用反射或IL技巧,并且有充分的理由。如果中间类允许您跳过此方法调用,则应该为其添加一个可以使用的特殊方法。这是“难”做的原因是你通常不应该这样做,你应该总是进入下一级别,以便它可以保持控制。
答案 2 :(得分:1)
这可以通过反思来完成。您获取当前类的Type,使用它来获取父类型,然后获取父类型的父类型。
该语言不直接支持的原因是它打破了继承的抽象模型。它与传统的面向对象设计并不完全兼容。
答案 3 :(得分:1)
我认为你的意思是从C?中的方法调用A.f()。
简短回答:你不能
但是,如果你可以控制B,你可以向B添加一个方法来明确地调用它的基础:
protected void BaseF()
{
base.f();
}
然后从C
调用该方法答案 4 :(得分:0)
试试这个:
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();
}
}
答案 5 :(得分:0)
从C中的函数,你可以调用base.f(),,这就是你应该做的。如果Bf()(你正在实际调用的那个)选择也调用base.f(),那么就可以达到你想要的效果,但完全取决于B的实现,不管是否发生了。
您可以尝试将C转换为A并调用f(),如下所示:
public class C : B {
public override f() {
((A) this).f();
}
}
但问题是C不知道f()在哪里被声明 - 它只知道在B中有一个可以被覆盖的实现,C不知道A存在。上面的示例实际上是一段糟糕的代码,如果A没有实现f(),则会产生编译时错误。
答案 6 :(得分:0)
使用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
答案 7 :(得分:0)
正如之前评论的那样,Virtual永远不会以这种方式被覆盖,你必须使用'new'而不是'override'。
以下是使用您的班级名称的示例:
这不是一个好习惯,因为它会变得非常混乱并且会破坏大部分预期的继承行为,而'new'关键字旨在强制将新的接口项强制转换为不打算被覆盖的类。
干杯, 杰森
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();
}
}
答案 8 :(得分:0)
这似乎是一个设计问题。
你有几个选择: