通用类的通用父类

时间:2008-11-04 06:38:29

标签: c# generics

我正在使用一个虚构的例子。说,我有一个Widget类,如:

abstract class Widget
{
Widget parent;
}

现在,我的其他类将从这个Widget类派生,但是假设我想在定义派生类型时在类中加入一些约束,这样只有特定的“类型”小部件才能成为特定类型的窗口小部件。

例如,我从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();

6 个答案:

答案 0 :(得分:8)

您应该能够使用仍然拥有非通用类Widget并使Widget<T>从中获得的代码:

public abstract class Widget
{
}

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

然后你需要弄清楚泛型类中的属性以及属于非泛型的内容......从经验来看,这可能是一个棘手的平衡行为。期待相当多的来回!

答案 1 :(得分:1)

使用接口:

interface IContainerWidget { }

class Widget
{
    private IContainerWidget Container;
}

class ContainerWidget : Widget, IContainerWidget
{
}

答案 2 :(得分:0)

我认为没有一种语言机制可以让你这样做。

但是,您可能希望使用 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。您是否愿意详细说明为什么您想要这样做?

答案 3 :(得分: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();
}

答案 4 :(得分: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();
    }
}

答案 5 :(得分: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();