我正在使用一个虚构的例子。说,我有一个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();
答案 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();