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

這時我有上面的結構。 擴展另一個基類的基類。 基類由兩個子類擴展。 BaseTestClass1Method的實現對於兩個子類是相同的。 如果可以從兩個父BaseTestClass1擴展,我將創建一個擴展BaseTestClass1的類,實現BaseTestClass1Method 這兩個子類將擴展BaseTestClass2和新類,這樣我只需要實現一次BaseTestClass1Method當我添加另一個BaseTestClass3(與BaseTestClass2相同的級別)從BaseTestClass1擴展並從中創建子類時,我有更多重復的代碼用於實現of BasetestClass1Method。 如何用正確的模式解決這個問題?

這是一個更實施的例子:

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

由於Diamond問題,不支持從兩個類(或抽象類)派生。 調用父方法時類型D的實例 - 它如何知道哪個父類?

在此輸入圖像描述

而不是具有許多抽象類的深度繼承樹使用接口和組合。

  • 用於定義API的接口
  • 通過特定實現的組合。

您的邏輯是通過某個接口定義的,並且具有針對該特定邏輯的不同具體類型。 然后像TestClassb這樣的類可以創建所需邏輯的實例,或者更好地依賴於它的構造函數:

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

在你的代碼注釋中,你說TestClass2B它具有與TestClassA相同的行為,但它取而代之的是BaseTestClass2 您應該正確考慮繼承樹。 TestClass2B應該是BaseTestClass2嗎? 或者它應該是一種TestClassA 如果它實際上是一種“類型” TestClassA那么繼承它。

所有答案都是針對特定領域的,但我建議您閱讀有關構圖的內容:它將幫助您了解您擁有的關系類型以及適合您情況的正確設計。

  1. 構成與繼承
  2. 喜歡構成而不是繼承?
  3. 繼承與構成的區別

另外也有一些很好的設計模式來看待,如StateStrategryDecoratordofactory

在看到Composition的優點以及何時使用它之后,你可以看看SOLIDInversion Of Control它將有助於它們很好地融合在一起。

使用接口而不是抽象類。 您可以從多個接口繼承,但只能從一個類繼承。

我不明白你為什么不在BaseTestClass2中重寫BaseTestClass1Method

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

要實現這樣的目標,您可以使用不同的模式

戰略模式: http//www.dofactory.com/net/strategy-design-pattern

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

您可以在BaseTestClass2中實現BaseTestClass1Method,以便TestClassA和TestClassB獲得相同的實現。 但是,根據您的要求,走這條路可能會繼承地獄。

您可以通過其構造函數(依賴注入(DI))將實現BaseTestClass1的實例傳遞給BaseTestClass2,而不是從BaseTestClass1繼承BaseTestClass2。 然后在TestClassA和TestClassB中簡單地調用實例中注入的BaseTestClass1Method方法。 這會將繼承級別降低到1。

使用諸如Autofac或Unity之類的DI容器將BaseTestClass1的正確實現注入BaseTestClass2的后代。

UPDATE

從你的例子開始吧

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 someTests2 = new SomeTests2(new ServerB());

請注意,我已刪除抽象類並將服務器實現注入新實例。

我放棄了TestClass(1..n),因為我看不到它們的需要,但只有你能知道答案。

此外,我已經編寫了這段代碼,所以它還沒有經過測試,也沒有檢查它是否編譯,但你應該能夠得到它的要點。 希望能幫助到你。

使用其他人建議的界面:

 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