C#如何在基的基中调用方法?
假设类A从类B继承,而类B又从类C继承。现在假设在A中定义了一个虚拟方法void f(),它在B和C中都被重写。从A中的任何方法调用B.f()只需使用base.f()即可。从中的方法调用C.f()怎么样?试试以下方法:C#如何在基的基中调用方法?,c#,C#,假设类A从类B继承,而类B又从类C继承。现在假设在A中定义了一个虚拟方法void f(),它在B和C中都被重写。从A中的任何方法调用B.f()只需使用base.f()即可。从中的方法调用C.f()怎么样?试试以下方法: C c = this; c.f(); 这将打印“C”: 这可以通过反射来实现。获取当前类的类型,使用该类型获取父类型,然后获取父类型的父类型 该语言不直接支持它的原因是它打破了继承的抽象模型。它与传统的面向对象设计并不兼容。您可以通过反射或IL代码生成。除此之外,你不能,你真的
C c = this;
c.f();
这将打印“C”:
这可以通过反射来实现。获取当前类的类型,使用该类型获取父类型,然后获取父类型的父类型
该语言不直接支持它的原因是它打破了继承的抽象模型。它与传统的面向对象设计并不兼容。您可以通过反射或IL代码生成。除此之外,你不能,你真的不应该,这听起来不是一个好的设计 当您在OOP中重写一个方法时,您基本上会说“对于这种类型,此方法将替换旧方法”,并规定您可以在必要时(通常是这样)调用替换的(重写的)方法
然而,你不能直接跳过一个关卡,除非你求助于反思或IL欺骗,这是有充分理由的。如果中间类允许您跳过此方法调用,则应向其添加一个可以使用的特殊方法。之所以“很难”做到这一点,是因为您通常不应该这样做,您应该始终转到下一个级别,以便它能够保持控制。我猜您的意思是从C中的方法调用A.f() 简单回答:你不能 但是,如果您可以控制B,则可以向B添加一个方法以显式调用其基:
protected void BaseF()
{
base.f();
}
然后从C调用该方法通常,通过重写一个类,您可以接受它提供了您想要的接口和一些行为。A不应该知道它的超类,除非它的超类以某种方式显式地公开。这实际上是可取的,因为当您使用子类B时,您不需要知道C是如何实现的。您甚至不应该知道C是如何实现的
如果b的f()调用base.f(),a的base.f()只需要调用它自己的base.f()就可以了。如果没有,唯一的方法就是通过基于反射的侵入式方法。如果您发现自己需要这样做,那么您的设计可能有错误(例如违反了德米特定律)。从C中的函数中,您可以调用base.f(),这就是您应该做的。如果B.f()(这是您正在有效地调用的)选择同时调用base.f(),那么这就实现了您想要的,但这完全取决于B的实现,取决于是否会发生 您可以尝试将C强制转换为A并调用f(),如下所示:
public class C : B {
public override f() {
((A) this).f();
}
}
但问题是C不知道f()是在哪里声明的——它只知道B中有一个可以重写的f()实现,C不知道A是否存在。上面的示例实际上是一段糟糕的代码,如果a没有实现f(),则会产生编译时错误。使用
new
而不是重写
是一种方法(虽然可以使用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
如前所述,虚拟机永远不能以这种方式重写,您必须使用“new”而不是“override” 下面是一个使用类名的示例: 这不是一个好的做法,因为它会变得非常混乱,并破坏许多预期的继承行为,“new”关键字旨在将新接口项强制到不打算被重写的类上 干杯, 杰森
这似乎是一个设计问题 您有几个选择:
可能重复:我想你的意思是从C中的方法调用A.f()?我只是在猜测,但是你不能将
这个转换为C吗?((C)本条);这似乎无法编译(无论如何,当我尝试它时)。你是否在考虑C++,它有类似的语法来调用继承链的方法?这不编译,也不工作,理论上,除非它们是静态的,否则不能调用这种方法,在这种情况下它们不能是虚拟的。对不起,我确实有C++的判断失误。用变通方法编辑。谢谢,这不是我自己的设计。在这种情况下,B类和C类是Telerik组件。类B提供了我所需要的大部分功能,但是为了实现一些功能,我需要在C中调用方法。
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();
}
}