c#继承多个父母

c#继承多个父母,c#,inheritance,multiple-inheritance,C#,Inheritance,Multiple Inheritance,在这一刻,我有上述建设。扩展另一个基类的基类。基类由两个子类扩展。对于这两个子类,baseTestClassMethod的实现是相同的。如果可以从两个父级进行扩展,我将创建一个类来扩展BaseTestClass1实现BaseTestClass1方法。然后,这两个子类将扩展BaseTestClass2和新类,这样我只需实现basetestclassmethod一次 当我添加另一个从BaseTestClass1扩展而来的BaseTestClass3(与BaseTestClass2级别相同)并从中创建

在这一刻,我有上述建设。扩展另一个基类的基类。基类由两个子类扩展。对于这两个子类,
baseTestClassMethod
的实现是相同的。如果可以从两个父级进行扩展,我将创建一个类来扩展
BaseTestClass1
实现
BaseTestClass1方法
。然后,这两个子类将扩展
BaseTestClass2
和新类,这样我只需实现
basetestclassmethod
一次 当我添加另一个从BaseTestClass1扩展而来的BaseTestClass3(与BaseTestClass2级别相同)并从中创建子类时,我有更多重复的代码用于BaseTestClass1方法的实现。 如何使用正确的模式解决此问题

下面是一个更实用的示例:

   namespace NUnitTestAbstract
{
    public abstract class BaseTestClass1
    {
        public abstract void BaseTestClass1Method();
    }

    public abstract class BaseTestClass2 : BaseTestClass1
    {
        // not overriding BaseTestClass1Method, child classes should do
        public void SomeTestMethodA() { }

        public void SomeTestMethodB() { }
    }

    public abstract class BaseTestClass3 : BaseTestClass1
    {
        // not overriding BaseTestClass1Method, child classes should do
        public void SomeTestMethodX() { }

        public void SomeTestMethodY() { }
    }

    public class TestClass2A : BaseTestClass2
    {
        public override void BaseTestClass1Method()
        {
            // do stuff
        }
    }

    public class TestClass2B : BaseTestClass2
    {
        public override void BaseTestClass1Method()
        {
            // do same stuff as TestClassA
        }
    }


    public class TestClass3A : BaseTestClass3
    {
        public override void BaseTestClass1Method()
        {
            // do stuff
        }
    }

    public class TestClass3B : BaseTestClass3
    {
        public override void BaseTestClass1Method()
        {
            // do same stuff as TestClass3A
        }
    }
}

使用接口而不是抽象类。您可以从多个接口继承,但只能从一个类继承。

由于以下原因,不支持从两个类(或抽象类)派生。调用父方法时,类型为
D
的实例-它如何知道哪个父方法

使用接口和组合代替具有许多抽象类的深层继承树

  • 用于定义API的接口
  • 组合要通过具体的实现
用一些接口定义逻辑,并为特定逻辑定义不同的具体类型。然后像
TestClassb
这样的类可以创建所需逻辑的实例,或者更好地说仍然依赖于它的构造函数:

namespace NUnitTestAbstract
{
    public interface IServer { }

    public abstract class ServerBase
    {
        public abstract IServer GetServerInstance();
    }

    public abstract class SomeTests1Base : ServerBase
    {
        // not overriding BaseTestClass1Method, child classes should do
        public void SomeTestMethodA() { }

        public void SomeTestMethodB() { }
    }

    public abstract class SomeTests2Base : ServerBase
    {
        // not overriding BaseTestClass1Method, child classes should do
        public void SomeTestMethodX() { }

        public void SomeTestMethodY() { }
    }

    public class TestClass2A : SomeTests1Base
    {
        public override IServer GetServerInstance()
        {
            IServer serverX = null;
            return serverX;
        }
    }

    public class TestClass2B : SomeTests1Base
    {
        public override IServer GetServerInstance()
        {
            IServer serverX = null;
            return serverX;
        }
    }


    public class TestClass3A : SomeTests2Base
    {
        public override IServer GetServerInstance()
        {
            IServer serverY = null;
            return serverY;
        }
    }

    public class TestClass3B : SomeTests2Base
    {
        public override IServer GetServerInstance()
        {
            IServer serverY = null;
            return serverY;
        }
    }
}

在您的代码注释中,您提到
TestClass2B
它与
TestClassA
具有相同的行为,但它是从
BaseTestClass2
派生的。您应该正确地考虑您的继承树。
TestClass2B
是否应该是
BaseTestClass2
的一种类型?还是应该是一种
TestClassA
? 如果它实际上是一种“类”
TestClassA
,则继承它

所有这些答案都是针对特定领域的,但我建议你阅读有关作文的内容:它将帮助你了解你的关系类型,以及什么是适合你的情况的正确设计

  • 此外,还有一些好的设计模式可供查看,例如下面的
    State
    Strategry
    Decorator


    在了解了
    合成的优点以及何时使用它之后,您可以查看
    固体
    控制反转
    ,这将有助于将它们完美地结合在一起。

    使用其他人建议的界面:

    public class Derived 
    {
        public Derived(ILogic someDependentLogic) { }
    }
    

    我不明白为什么不重写BaseTestClass2中的BaseTestClass1方法

     namespace NUnitTestAbstract
        {
            public interface IBaseTes1
            {
                void BaseTestClass1Method();
            }
    
            public abstract class BaseTestClass2 : IBaseTes1
            {
                void IBaseTes1.BaseTestClass1Method()
                {
    
                }
    
                // not overriding BaseTestClass1Method, child classes should do
                public void SomeTestMethodA() { }
    
                public void SomeTestMethodB() { }
            }
    
            public class TestClassA : BaseTestClass2
            {
            }
    
            public class TestClassb : BaseTestClass2
            {
            }
        }
    
    为了达到这样的目标,你可以使用不同的模式,比如

    战略模式:


    状态模式:

    您可以在BaseTestClass2中实现BaseTestClassMethod,以便TestClassA和TestClassB获得相同的实现。然而,根据您的需求,走这条路可能会导致继承失败

    您可以通过其构造函数(依赖注入(DI))将实现BaseTestClass1的实例传递给BaseTestClass2,而不是从BaseTestClass1继承BaseTestClass2。然后在TestClassA和TestClassB中,只需调用注入实例的BaseTestClassMethod方法。这将您的继承级别降低到1

    使用DI容器(如Autofac或Unity)将BaseTestClass1的正确实现注入BaseTestClass2的Decentant中

    更新

    从你的例子开始

        public abstract class BaseTestClass2 : BaseTestClass1
        {
            public override void BaseTestClass1Method()
            {
                // do same stuff as TestClassA
            }
        }
    
    var someTests1=newsometests1(newservera()); var someTests2=newsometests2(newserverb())

    注意,我已经删除了抽象类,并将服务器实现注入到新实例中

    我放弃了TestClass(1..n),因为我看不出有必要使用它们,但只有您知道答案


    此外,我还动态编写了这段代码,因此它没有经过测试,也没有检查它是否编译,但您应该能够了解它的要点。希望有帮助。

    我没有找到正确的接口解决方案。BaseTestClass2实现两个测试方法,然后由两个子类共享。BaseTestClass1还应该有一个实现,我可以和两个子类共享。diamond问题几年前就解决了吗?我想Bob叔叔甚至讨论过它。@WernerKellens-看起来
    TestClassb
    更像是
    TestClassA
    的一种类型,而不是基本类型,那么也许你应该让它从
    TestClassA
    派生出来。但是,您仍然会遇到深层继承树,这会降低代码的灵活性—使用组合有助于解决这一问题it@WernerKellens-这个答案帮助你解决问题了吗?@WernerKellens-很高兴听到:)SOLID真的让生活简单多了。我找不到正确的接口解决方案。BaseTestClass2实现两个测试方法,然后由两个子类共享。BaseTestClass1还应该有一个我可以和两个子类共享的实现。我想这是唯一的解决办法。我用一个扩展的例子编辑了这个问题。问题是BaseTestClass2不应该实现BaseTestClass1方法。如果BaseTestClass1方法真的是一样的,那么为什么不让BaseTestClass1具体化并在那里实现该方法呢?您可以对子类中可能不同的任何属性/方法进行受保护的重写。或者我错过了什么?谢谢,举个例子就好了!谢谢,不,我可以在我的实际实现中尝试一下,因为子类之间的实现可能不同。我已经改变了我的借口。实现与fo不同
    namespace NUnitTestAbstract
    {
        public interface IServer { }
    
        public class BaseServer()
        {
            private IServer _server;
    
            public BaseServer(IServer server)
            {
                _server = server;
            }
    
            public IServer GetServerInstance()
            {
                return _server;
            }
        }
    
        public class SomeTests1 : ServerBase
        {
            // not overriding BaseTestClass1Method, child classes should do
            public void SomeTestMethodA() { }
    
            public void SomeTestMethodB() { }
        }
    
        public class SomeTests2 : ServerBase
        {
            // not overriding BaseTestClass1Method, child classes should do
            public void SomeTestMethodX() { }
    
            public void SomeTestMethodY() { }
        }
    }
    
    public class ServerA : IServer
    {
        //Implementation
    }
    
    public class ServerB : IServer
    {
        //Implementation
    }