2013-03-08 94 views
3

我有一個抽象類,抽象類採用實現類的類型參數。我可以通過這樣的泛型實現這一點:如何使用實現類的參數創建抽象方法

abstract class Clazz<T> 
{ 
    public abstract void CopyFrom(Clazz<T> source); 
} 

class MyClass : Clazz<MyClass> 
{ 
    public override void CopyFrom(Clazz<MyClass>) 
    { 
    // implementation 
    } 
} 

不幸的是,我需要在實現類的一個Clazz<T>元素的列表。 那麼我怎麼能做到這一點?

  • 原因List<Clazz<T>>不起作用。
  • List<Clazz<MyClass>>限制性太強。
  • 刪除泛型和抽象方法確實有效(我當前的解決方案),但是這樣我可以忘記在其中一個實現類中實現CopyFrom()方法。

編輯:又來了一個更詳細的例子: 我有一個抽象類:

abstract class Clazz<T> 
{ 
    public abstract void CopyFrom(Clazz<T> source); 
    // ... 
} 

而派生類:

class MyDerivedClass : Clazz<MyDerivedClass > 
{ 
    public string Text; 
    private readonly List<MySubClass> _list = new List<MySubClass>(); 

    public override void CopyFrom(MyDerivedClass source) 
    { 
     Text = source.Text; 
    } 

    private List<Clazz> GetAllItems() 
    { 
     List<Clazz> list = new List<Clazz>(); 
     list.Add(this); 
     list.AddRange(_list); 
    } 


    private class MySubClass : Clazz<MySubClass> 
    { 
     public int Number; 

     public override void CopyFrom(MySubClass source) 
     { 
      Number = source.Number; 
     } 
    } 
} 

還有一些其他的推導類,GetAllItems()方法只在MyDerivedClass需要。

+1

你需要哪個清單?作爲抽象方法的參數,還是僅僅作爲派生類中的字段/屬性? – 2013-03-08 12:08:03

+0

請你能解釋爲什麼'List >'太嚴格了嗎? – qujck 2013-03-08 12:09:36

+0

'List >'因爲我需要用不同類型的元素填充它,所有元素都來自'Clazz '',所以限制性太強。 – Tarkil 2013-03-08 12:19:35

回答

1

您也可以使各自的方法具有通用性,並引入一個約束條件,該約束條件需要考慮T。如果我的理解以及你想達到什麼,你可以這樣做:

abstract class Clazz<T> 
{ 
    public abstract void CopyFrom(Clazz<T> source); 

    public abstract void ProcessList<TDescendant>(List<TDescendant> list) 
     where TDescendant : Clazz<T>; 
} 

class MyClass : Clazz<MyClass> 
{ 
    public override void CopyFrom(Clazz<MyClass> source) 
    { 
     // implementation 
    } 

    public override void ProcessList<TDescendant>(List<TDescendant> list) 
    { 
     // implementation 
    } 
} 

你也可以很容易地包括在子列表處理,類似這樣的:

class MyOtherClass : Clazz<MyOtherClass> 
{ 
    public override void CopyFrom(Clazz<MyOtherClass> source) 
    { 
     // implementation 
    } 

    // this list processing is inherited 
    public override void ProcessList<TDescendant>(List<TDescendant> list) 
    { 
     // implementation 
    } 

    // this list processing is specific to this descendant only 
    public void ProcessMyClassList<TDescendant>(List<TDescendant> list) 
     where TDescendant : Clazz<TMyClass> 
    { 
     // implementation 
    } 
} 

然後使用可申報的後裔MyClass,這又是一個Clazz<T>TMyClass

class MyDescendant : MyClass 
{ 
} 

以下工作:

List<MyDescendant> list = new List<MyDescendant>(); 
new MyClass().ProcessList(list); 

如果是MyOtherClass,情況有點不同。 ProcessMyClassList接受Clazz<T>或其後代名單;然而,不是那些與MyOtherClass有關的,而是那些與「醇」MyClass有關的。此代碼的工作:

List<MyDescendant> list = new List<MyDescendant>(); 
new MyOtherClass().ProcessMyClassList(list); // this works 

但以下不會編譯:

List<MyOtherClass> list = new List<MyOtherClass>(); 
new MyOtherClass().ProcessList(list);  // this works 
new MyOtherClass().ProcessMyClassList(list); // this doesn't 
+0

我還沒有測試過,但這樣我就不得不在所有派生類中實現方法'ProcessList',不是嗎?正如我已經回答了上面的問題,我確實只需要在一個派生類中的列表。 – Tarkil 2013-03-08 12:27:44

+1

然後聲明它只是在派生類中:-) – 2013-03-08 12:37:31

+0

對不起,如果我有點慢,但你能修改你的例子,告訴我你的意思嗎?讓方法在其他派生類中未實現,或從Clazz中移除抽象定義? – Tarkil 2013-03-08 14:01:56

1

會這樣就夠了?沒有更多的細節,很難說。

interface ICopyMaker 
{ 
    void CopyFrom(ICopyMaker source); 
} 

abstract class Clazz<T> : ICopyMaker 
{ 
    public abstract void CopyFrom(Clazz<T> source); 

    void ICopyMaker.CopyFrom(ICopyMaker source) 
    { 
     var src = source as Clazz<T>; 
     if (src == null) return; // know how to copy only from the instances of the same type 

     CopyFrom(src); 
    } 
} 

class MyClass : Clazz<MyClass> 
{ 
    private List<ICopyMaker> _list = new List<ICopyMaker>(); 

    public override void CopyFrom(Clazz<MyClass> c) 
    { 
    //implementation 
    } 
} 
+0

不幸的是,'CopyFrom(Clazz c)'無法訪問'MyClass:Clazz '的字段。 (無法解析符號)。 – Tarkil 2013-03-08 13:30:45

+0

CopyFrom(Clazz c)是MyClass中聲明的方法。它始終可以訪問MyClass的任何成員。你能否提供更多關於你所得到的錯誤的細節? – anikiforov 2013-03-08 15:20:06

0

感謝的每個人都對你的答案,但我想我已經找到了一個解決方案,我可以住在一起: 我將刪除仿製藥,並在解決方案從anikiforov添加一個類型檢測,如:

摘要類:

abstract class Clazz 
{ 
    public abstract void CopyFrom(Clazz source); 
} 

和派生類:

class MyDerivedClass : Clazz 
{ 
    public string Text; 
    private List<MyNestedClass> _list; 

    public override void CopyFrom(Clazz source) 
    { 
     var src = source as MyDerivedClass; 
     if (src == null) return; 
     Text = src.Text; 
    } 

    public List<Clazz> GetAllItems() 
    { 
     var list = new List<Clazz>(); 
     list.Add(this); 
     list.AddRange(_list); 
     return list; 
    } 

    class MyNestedClass : Clazz 
    { 
     public int Number; 
     public override void CopyFrom(Clazz source) 
     { 
      var src = source as MyNestedClass; 
      if (src == null) return; 
      Number = src.Number; 
     } 
    } 
}