簡體   English   中英

在基本抽象類中使用派生類型

[英]Use derived type in base abstract class

好吧,我有一些從基類派生的不同類。 此基類是包含commom方法的抽象。

其中一個方法是Copy方法,它應該出現在所有派生類中,所以,我把它放在基類中。 但是,我希望它返回derived type而不是基礎或對象。

我得到的解決方案是使用類型參數:

abstract class CopyableClass<T>
{
    public abstract T Copy();
}

class DerivedClass : CopyableClass<DerivedClass>
{
    public override DerivedClass Copy()
    {
        //do what is needed for copy and return a new DerivedClass
    }
}

所以,這里的主要目的是

刪除基類中的type參數,仍然使該方法返回相應的派生類型。


一個解決方法。

到目前為止我能做的最好的事情是以下評論之一,但它仍然使用通用參數

abstract class BaseClass
{
    //base methods not related to deriving type
}

interface ICopyable<T>
{
     T Copy();
}

class DerivedClass : BaseClass, ICopyable<DerivedClass>
{
    public DerivedClass Copy()
    {
        //do what is needed for copy and return a new DerivedClass
    }
}

你不能真的。 基類不可能知道所有未來的實現。 您將不得不求助於通用抽象類(就像您所做的)類型或通用的Copy方法。

public abstract class CopyableClass
{
    public abstract T Copy<T>() where T : CopyableClass;
}

public class DerivedClass : CopyableClass
{
    public override T Copy<T>()
    {
        if(typeof(T) != typeof(DerivedClass))
            throw new ArgumentException();

        // return your copy
    }
}

或者,如果要在基類中概括類型檢查:

public abstract class CopyableClass
{
    public T Copy<T>() where T : CopyableClass
    {
        if(GetType() != typeof(T))
            throw new ArgumentException();

        return (T) Copy();
    }

    protected abstract CopyableClass Copy();
}

public class DerivedClass : CopyableClass
{
    protected override CopyableClass Copy()
    {
        return // Your copy;
    }
}

請注意,第二種方法將大量信任放入派生類的實現中,因為它將盲目地轉換抽象方法的返回值。 編譯器將允許您在派生類型中返回另一個類型,實現CopyableClass,但它將是運行時錯誤。 如果您對所有派生實現具有絕對控制權(即您的抽象類也具有內部構造函數),則這不是問題。

您實際上想要在基類中實現副本並讓它返回T 這將使您使用類型參數調用它並返回該類型。

public static T Copy<T>() where T : CopyableClass
{
    T retVal = new T();
    // do whatever copying is required
    return retVal;
}

打電話給你做;

DerivedClass d = Copy<DerivedClass>();

實際執行復制的代碼可能需要更多的工作來制作泛型,但是值得付出努力,因為您將擁有適用於任何派生類型的Copy()的單個實現。 我不知道該方法中有什么邏輯,所以我只是把事情搞砸了。 另外,我建議一般檢查泛型。 對於像這樣的事情,它們通常是最好的選擇。 如果你的實現需要對基類是唯一的'保持相同的方法定義但是使它成為抽象,然后在基類中重寫它。

這將允許您將此基類置於派生類型並返回它。

public abstract class BaseClass<TDerived> : where TDerived: BaseClass<TDerived>
{
   public TDerived DoSomethingCommon(string param)
   {
      var derivedType = (TElement)this;
      //do something.
      return derivedType;
   }
}

這個解決方案涉及中產階級,但我認為它更符合您的需求。 至少你可以獲得隔離復制代碼的好處

    public abstract class BaseClass
    {
    }

    public abstract class CopyableClass<T> : BaseClass
        where T: BaseClass, new()
    {
        public T Copy()
        {
            var copy = new T(); // Creating a new instance as proof of concept

            return copy;
        }
    }

    public class DerivedClass : CopyableClass<DerivedClass>
    {
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM