Generic parent for a common class

I am using a fictional example for this. Say I have a Widget class, for example:

abstract class Widget { Widget parent; } 

Now my other classes will be derived from this Widget class, but suppose I want to put some restriction on the class when defining derived types, so that only the specific "type" of the widget can be the parent of a particular type of Widget.

For example, I got two more widgets from the Widget class, WidgetParent and WidgetChild. By defining a child class, I want to define the type of the parent as WidgetParent, so I do not need to type the parent cast every time I use it.

Exactly what I would like to do is the following:

 // This does not works! class Widget<PType>: where PType: Widget { PType parent; } class WidgetParent<Widget> { public void Slap(); } class WidgetChild<WidgetParent> { } 

So, when I want to access the parent element of WidgetChild, instead of using it like this:

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

I want to use it this way (if I could use generics):

 wc.parent.Slap(); 
+4
source share
6 answers

You should be able to use the code that you have, still having a non-generic Widget class and making Widget<T> :

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

Then you need to find out what belongs to the tribal class and what belongs to the non-tribal ... from experience, this can be a difficult balancing act. Expect to go back and forth for the amount!

+8
source

Use Interfaces:

 interface IContainerWidget { } class Widget { private IContainerWidget Container; } class ContainerWidget : Widget, IContainerWidget { } 
+1
source

I do not think that there is a language mechanism that will allow you to do this.

However, you can use the Factory pattern to separate the construction of the class from the class itself .

Say create a WidgetFactory class

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

And for child classes, you also create their factory. Let's say WidgetParentFactory or WidgetChildFactory, or you can create a common factory:

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

Then, from the CreateWidget () method, you can control the creation of the class so that you do not create invalid child types.

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

This should do the trick for you.

ps Could you explain why you wanted to do this?

0
source

It seems you are misleading type parameters and inheritance. This should work:

 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(); } 
0
source

Here is my blow to organizing this.

 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
source

I had a similar problem and it was adapted for this (hopefully)

Main code

 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) { } } 

Example:

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

All Articles