2008-11-04 51 views
4

我正在使用一個虛構的例子。我說,我有一個Widget類,如:通用類的通用父類

abstract class Widget 
{ 
Widget parent; 
} 

現在,我的其他類將從該小組件類派生,但假設我想提出一些約束的類在定義派生類型,僅特定的窗口小部件的「類型」可以是特定類型的窗口小部件的父類。

例如,我從Widget類WidgetParent和WidgetChild派生了兩個小部件。在定義子類時,我想將父類型定義爲WidgetParent,以便每次使用時都不必鍵入父類型。

準確地說,我也喜歡做的是這樣的:

// This does not works! 
class Widget<PType>: where PType: Widget 
{ 
    PType parent; 
} 

class WidgetParent<Widget> 
{ 
    public void Slap(); 
} 

class WidgetChild<WidgetParent> 
{ 
} 

所以,當我想訪問的,而不是用這種方式WidgetChild的母公司:

WidgetParent wp = wc.parent as WidgetParent; 
if(wp != null) 
{ 
    wp.Slap(); 
} 
else throw FakeParentException(); 

我想用這種方式(如果我可以使用泛型):

wc.parent.Slap(); 

回答

8

您應該能夠通過仍然具有非通用類Widget,使Widget<T>使用你已經得到了代碼從它派生:

public abstract class Widget 
{ 
} 

public abstract class Widget<T> : Widget where T : Widget 
{ 
} 

然後,您需要制定出了一般屬於什麼類和屬於非泛型......從經驗來看,這可能是一個棘手的平衡行爲。預計會來回相當數量!

0

我不認爲有一種語言機制,即w應該允許你這樣做。

但是,您可能希望使用Factory pattern將類的構造與類本身分開

說,作一個WidgetFactory類

class WidgetFactory 
{ 
    Widget CreateWidget() 
    { 
     return new Widget(); 
    } 
} 

而對於子類,你會做自己的工廠爲好。再說了,一個WidgetParentFactory或WidgetChildFactory或者你可以做一個普通的工廠:

class WidgetFactory<T> where T : Widget 
{ 
    T CreateWidget() 
    { 
     return new T(); 
    } 
} 

然後從CreateWidget()方法,你可以控制類的實例,這樣無法創建無效子類型。

class WidgetFactory<T> where T : Widget 
{ 
    T CreateWidget() 
    { 
     if (/*check the type T inheritance here*/) 
      return new T(); 
     else 
      throw new Exception("Invalid inheritance"); 
    } 
} 

這應該對你有用。

p.s.您是否在意詳細說明爲什麼您想這樣做?

+0

謝謝你的努力,chakrit。我詳細說明了使用情況。 – nullDev 2008-11-04 07:09:57

+0

好吧,我現在看到。我回家後會編輯。 – chakrit 2008-11-04 07:50:07

0

你似乎混淆了類型參數和繼承。這應該工作:

class Widget<PType> where PType :new() 
{ 
    public PType parent = new PType(); 
} 

class ParentType {} 

class WidgetParent : Widget<ParentType> 
{  
    public void Slap() {Console.WriteLine("Slap"); } 
} 

class WidgetChild : Widget<WidgetParent> 
{ 
} 
public static void RunSnippet() 
{ 
    WidgetChild wc = new WidgetChild(); 
    wc.parent.Slap(); 
} 
1

使用接口:

interface IContainerWidget { } 

class Widget 
{ 
    private IContainerWidget Container; 
} 

class ContainerWidget : Widget, IContainerWidget 
{ 
} 
0

這裏是我在組織這次刺。

public interface IWidget 
{ 
    void Behave(); 
    IWidget Parent { get; } 
} 

public class AWidget : IWidget 
{ 
    IWidget IWidget.Parent { get { return this.Parent; } } 
    void IWidget.Behave() { this.Slap(); } 

    public BWidget Parent { get; set; } 
    public void Slap() { Console.WriteLine("AWidget is slapped!"); } 
} 

public class BWidget : IWidget 
{ 
    IWidget IWidget.Parent { get { return this.Parent; } } 
    void IWidget.Behave() { this.Pay(); } 

    public AWidget Parent { get; set; } 
    public void Pay() { Console.WriteLine("BWidget is paid!"); } 
} 

public class WidgetTester 
{ 
    public void AWidgetTestThroughIWidget() 
    { 
     IWidget myWidget = new AWidget() { Parent = new BWidget() }; 
     myWidget.Behave(); 
     myWidget.Parent.Behave(); 
    } 
    public void AWidgetTest() 
    { 
     AWidget myWidget = new AWidget() { Parent = new BWidget() }; 
     myWidget.Slap(); 
     myWidget.Parent.Pay(); 
    } 

    public void BWidgetTestThroughIWidget() 
    { 
     IWidget myOtherWidget = new BWidget() { Parent = new AWidget() }; 
     myOtherWidget.Behave(); 
     myOtherWidget.Parent.Behave(); 
    } 

    public void BWidgetTest() 
    { 
     BWidget myOtherWidget = new BWidget() { Parent = new AWidget() }; 
     myOtherWidget.Pay(); 
     myOtherWidget.Parent.Slap(); 
    } 
} 
0

我也有類似的問題,並適應它,以適應這個(希望)

主代碼

public class Parent<T> 
    where T : Child<T> 
{ 
    public Parent() { } 


    public T Get() 
    { 
     return Activator.CreateInstance(typeof(T), new object[] { this }) as T; 
    } 
} 

public class Child<T> 
    where T : Child<T> 
{ 
    Parent<T> _parent; 

    public Parent<T> Parent { get { return _parent; } } 

    public Child(Parent<T> parent) 
    { 
     _parent = parent; 
    } 
} 


public class ItemCollection : Parent<Item> 
{ 

} 

public class Item : Child<Item> 
{ 
    public Item(Parent<Item> parent) 
     : base(parent) 
    { 
    } 
} 

例子:

ItemCollection col = new ItemCollection(); 
Item item = col.Get(); 
item.Parent.Slap();