【问题标题】:Emulating Multiple Inheritance C# [duplicate]模拟多重继承 C# [重复]
【发布时间】:2020-06-08 11:24:39
【问题描述】:
public class A2
{
  protected virtual void f() {Console.WriteLine("from A2");}
  protected virtual void g() {Console.WriteLine("From A2");}
  protected virtual void h1() {Console.WriteLine("from A2");}
}

public class B2
{
  protected virtual void f() {Console.WriteLine("B2");}
  protected virtual void g() {Console.WriteLine("B2");}
  protected virtual void h2() {Console.WriteLine("B2");}
}

给出上面的代码,我试图通过创建一个新类来继承这两个类的所有功能,如下所示:

public class C2 
{
    private A2 a2 = new A2();
    private B2 b2 = new B2();

    public void f()
    {
        a2.f();
    }

    public void h1()
    {
        a2.h1();
    }

    public void g()
    {
        b2.g();
    } 

    public void h2()
    {
        b2.h2();
    } 


    static public void Main() 
    {
        C2 n = new C2();
        n.f();
        n.g();
        n.h1();
        n.h2();

    }

}

但是,当我尝试编译程序时,我遇到了一个错误,即我无法访问受保护的方法。 如何在不修改 A2B2 类的情况下继承所有功能?

【问题讨论】:

  • 这不是继承,而是将 A2 和 B2 作为依赖项。非常不一样。由于成员标记为protected,因此无法从类外部或从其继承的类访问它们。
  • 您可以创建一个继承自A2 的包装类,然后提供new 方法传递到基本实现,将受保护的方法公开为公共方法。
  • C# 不支持多重继承,除非您从类派生,否则您无法访问protected 字段。您必须将它们公开或编写一个暴露它们的包装器。
  • @RufusL 你应该提到我们在C#中使用接口来实现多类继承

标签: c#


【解决方案1】:

派生在公共方法中公开行为的类。从派生类型组成复合类。

public class A2_Derived : A2
{
    public void FMethod() => f();
    public void GMethod() => g();
    public void H1Method() => h1();
}

public class B2_Derived : B2
{
    public void FMethod() => f();
    public void GMethod() => g();
    public void H2Method() => h2();
}

public class C2 
{
    private A2_Derived a2 = new A2_Derived();
    private B2_Derived b2 = new B2_Derived();

    // implement the methods you need...
}

【讨论】:

  • 最好不要使用像 'new' 这样的晦涩修饰符,因为它们在强制转换时表现得非常愚蠢。在生产开发中,它注定要在审查级别。使用接口。
  • 这个例子没有任何方法可以让new 隐藏一个继承的成员。基类方法命名为fgh1h2。派生类使用FGH1H2。或者他们在最后一次编辑之前:]。
  • 是的,该案例旨在传达我们并未尝试保留方法签名。重命名方法以更明确地传达这一点。
【解决方案2】:

这是 C# 抽象类和虚拟类的缺点之一 - 没有多重继承。抽象本质上是对父级的依赖,但为什么要有一个依赖呢?

至于你的问题的解决方案,你需要在合并之前将它们公开:

public class A2
{
  protected virtual void f() {Console.WriteLine("from A2");}
  protected virtual void g() {Console.WriteLine("From A2");}
  protected virtual void h1() {Console.WriteLine("from A2");}
}

//make a wrapper which will publish protected methods
//ADVICE: always use interfaces, they MUCH more flexible as you will see in your own example, use abstract/static modifier with caution.
public interface IA2
{
    void f_public();
    void g_public();
    void h1_public();
}
public class PublicA2 : A2, IA2
{  
   public void f_public(){f();}
   public void g_public(){g();}
   public void h1_public(){h1();}
}
//do the same for B2

然后你可以将它们组合起来,甚至用对应的接口标记它们:

public class C2 : IA2, IB2
{
    private readonly IA2 _a2;
    private readonly IB2 _b2;

    public C2(IA2 a2, IB2 b2)
    {
        _a2 = a2;
        _b2 = b2;
    }

    public void f_public()
    {
        _a2.f_public();
    }

    public void h1_public()
    {
        _a2.h1_public();
    }

    public void g_public()
    {
        _b2.g_public();
    } 

    public void h2_public()
    {
        _b2.h2_public();
    } 
}

【讨论】:

  • “这是抽象类和虚拟类的缺点之一 - 没有多重继承” - 嗯……不完全确定你在哪里看到这两个概念之间的联系……C++ 有抽象类和虚拟类...但它有多重继承就好了。你可能想说点不同的东西……
  • 好吧,如果我能这么说,在 C++ 中会好得多。在 C# 中,无论微软有什么疯狂的原因,这都是被禁止的。我是在 C# 的上下文中说的,许多其他语言都有类,我并不是指所有的类,因为例如 Python 将允许多重继承。
猜你喜欢
  • 2017-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-25
  • 1970-01-01
  • 1970-01-01
  • 2011-03-13
相关资源
最近更新 更多