简体   繁体   English

c#继承多个父母

[英]c# inheritance multiple parents

   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
        }
    }
}

At this moment I have the above construction. 这时我有上面的结构。 A base class extending another base class. 扩展另一个基类的基类。 The base class is extended by two child classes. 基类由两个子类扩展。 The implementation of BaseTestClass1Method is the same for the two child classes. BaseTestClass1Method的实现对于两个子类是相同的。 If it was possible to extends from two parents I would create a class extending BaseTestClass1 implementing BaseTestClass1Method . 如果可以从两个父BaseTestClass1扩展,我将创建一个扩展BaseTestClass1的类,实现BaseTestClass1Method The two child classes would then extend BaseTestClass2 and the new class so that I only have to implement BaseTestClass1Method once When I add another BaseTestClass3 (same level as BaseTestClass2) extending from BaseTestClass1 and create child classes from it, I have more duplicate code for the implementation of BasetestClass1Method. 这两个子类将扩展BaseTestClass2和新类,这样我只需要实现一次BaseTestClass1Method当我添加另一个BaseTestClass3(与BaseTestClass2相同的级别)从BaseTestClass1扩展并从中创建子类时,我有更多重复的代码用于实现of BasetestClass1Method。 How can I solve this with the correct pattern? 如何用正确的模式解决这个问题?

Here's a more implemented example: 这是一个更实施的例子:

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;
        }
    }
}

deriving from two classes (or abstract classes) is not supported due to the Diamond problem . 由于Diamond问题,不支持从两个类(或抽象类)派生。 An instance of type D when calling a parent method - how does it know of which parent? 调用父方法时类型D的实例 - 它如何知道哪个父类?

在此输入图像描述

Instead of deep inheritance trees with many abstract classes use interfaces and composition. 而不是具有许多抽象类的深度继承树使用接口和组合。

  • Interfaces to define the API 用于定义API的接口
  • Composition to pass specific implementation. 通过特定实现的组合。

Have your logic be defined with some interface and have the different concrete types for that specific logic. 您的逻辑是通过某个接口定义的,并且具有针对该特定逻辑的不同具体类型。 Then a class like TestClassb can create an instance of the desired logic or better still depend on it in its constructor: 然后像TestClassb这样的类可以创建所需逻辑的实例,或者更好地依赖于它的构造函数:

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

In your code comments you say about TestClass2B that it has same behavior as TestClassA but it instead derives from BaseTestClass2 . 在你的代码注释中,你说TestClass2B它具有与TestClassA相同的行为,但它取而代之的是BaseTestClass2 You should properly think about your inheritance tree. 您应该正确考虑继承树。 Should TestClass2B be a type of BaseTestClass2 ? TestClass2B应该是BaseTestClass2吗? Or should it be a type of TestClassA ? 或者它应该是一种TestClassA If it is actually a "kind of" TestClassA then inherit it instead. 如果它实际上是一种“类型” TestClassA那么继承它。

All together the answers are domain specific but I recommend you read about composition: It will help you understand what kind of relationships you have and what is the correct design for your situation. 所有答案都是针对特定领域的,但我建议您阅读有关构图的内容:它将帮助您了解您拥有的关系类型以及适合您情况的正确设计。

  1. Composition vs. Inheritance 构成与继承
  2. Prefer composition over inheritance? 喜欢构成而不是继承?
  3. Difference between Inheritance and Composition 继承与构成的区别

Further there are some good Design Patterns to look at, such as State , Strategry , Decorator under dofactory 另外也有一些很好的设计模式来看待,如StateStrategryDecoratordofactory

After seeing the advantages of Composition and when to use it you can have a look at SOLID and Inversion Of Control it will help it all fit nicely together. 在看到Composition的优点以及何时使用它之后,你可以看看SOLIDInversion Of Control它将有助于它们很好地融合在一起。

Use interfaces instead of abstract classes. 使用接口而不是抽象类。 You can inherit from multiple interfaces, but only from one class. 您可以从多个接口继承,但只能从一个类继承。

I didn't understand why are you just not overriding BaseTestClass1Method in BaseTestClass2 我不明白你为什么不在BaseTestClass2中重写BaseTestClass1Method

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

To achieve such goal you might use different patterns like 要实现这样的目标,您可以使用不同的模式

Strategy Pattern : http://www.dofactory.com/net/strategy-design-pattern 战略模式: http//www.dofactory.com/net/strategy-design-pattern

State Pattern : http://www.dofactory.com/net/state-design-pattern 州模式: http//www.dofactory.com/net/state-design-pattern

you could implement BaseTestClass1Method in BaseTestClass2 so that both TestClassA and TestClassB get the same implementation. 您可以在BaseTestClass2中实现BaseTestClass1Method,以便TestClassA和TestClassB获得相同的实现。 Depending on your requirements however, going this path might end in inheritance hell. 但是,根据您的要求,走这条路可能会继承地狱。

Instead of inheriting BaseTestClass2 from BaseTestClass1 you can pass an instance that implements BaseTestClass1 into BaseTestClass2 via its constructor (dependence injection (DI)). 您可以通过其构造函数(依赖注入(DI))将实现BaseTestClass1的实例传递给BaseTestClass2,而不是从BaseTestClass1继承BaseTestClass2。 Then in TestClassA and TestClassB simply call the BaseTestClass1Method method of the injected in instance. 然后在TestClassA和TestClassB中简单地调用实例中注入的BaseTestClass1Method方法。 This reduces your inheritance levels to just 1. 这会将继承级别降低到1。

Use a DI container such as Autofac or Unity to inject the correct implentation of BaseTestClass1 into decendants of BaseTestClass2. 使用诸如Autofac或Unity之类的DI容器将BaseTestClass1的正确实现注入BaseTestClass2的后代。

UPDATE UPDATE

So working from your example 从你的例子开始吧

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
}

var someTests1 = new SomeTests1(new ServerA()); var someTests1 = new SomeTests1(new ServerA()); var someTests2 = new SomeTests2(new ServerB()); var someTests2 = new SomeTests2(new ServerB());

Note that I've removed the abstract classes and injected the server implementations into the new instances. 请注意,我已删除抽象类并将服务器实现注入新实例。

I've dropped the TestClass(1..n) because I cannot see a need for them but only you can know the answer to that. 我放弃了TestClass(1..n),因为我看不到它们的需要,但只有你能知道答案。

Also I've written this code on the fly so it has not been tested nor have I checked if it even compiles but you should be able to get the gist of it. 此外,我已经编写了这段代码,所以它还没有经过测试,也没有检查它是否编译,但你应该能够得到它的要点。 Hope it helps. 希望能帮助到你。

Use the interface as suggested by others: 使用其他人建议的界面:

 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
        {
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM