2013-07-02 115 views
5

好吧,我有許多不同的派生於基類的類。 該基類是一個包含通用方法的抽象。在基本抽象類中使用派生類型

其中一種方法是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 
    } 
} 

因此,主要目的這裏是

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


一個解決辦法。

我能做迄今爲止最好的事情是下面的意見之一,但它仍然採用了通用的參數

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

那麼你的問題是什麼? – evanmcdonnal

+0

可能會更好地實現這個通用接口? –

+0

如何刪除基類中的類型參數並仍然使該方法返回相應的派生類型。 –

回答

4

你真的不能。基類不可能知道所有未來的實現。你將不得不求助於一個通用的抽象類(像你一樣)或者一個通用的方法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,但它將是一個運行時錯誤。如果你對所有的派生實現有絕對的控制權(即你的抽象類也有一個內部構造函數),這不是問題。

0

你實際上想要在基類中實現拷貝並讓它返回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(),對於任何派生類型工作的努力。我不知道該方法屬於什麼邏輯,所以我只是把事情弄糟了。另外,我建議一般檢查泛型。他們通常是這樣的事情的最佳選擇。如果您的實現需要對基類是唯一的,請保留相同的方法定義,但將其抽象化,然後在基類中重寫它。

0

這將允許您將此基類映射到派生類型並返回它。

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

該解決方案涉及一箇中產階級,但我認爲它更符合你在找什麼。至少你得到隔離你的複製代碼的可能好處

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> 
    { 
    } 
相關問題