I have an abstract class BaseItem declared like this:
public abstract class BaseItem
{
public BaseItem Parent { get; protected set; }
public List<BaseItem> Children = new List<BaseItem>();
public abstract string Function1();
}
Basically, i'm trying to implement a design where each Item has a parent that will be of one specific type and children that will be of a different type.
For example, ItemA would have children all of ItemB type. Then ItemB would have a parent of ItemA type and children all of ItemC type. ItemC would have parent of ItemB and children of ItemD type.
I thought it would be neater to do this using generics to avoid unnecessary casts since i know what type the parent and children will be for each of my inherited classes. So i came up with something like this:
public abstract class AbstractBase
{
public abstract string Function1();
}
public abstract class BaseItem<T1, T2> : AbstractBase
where T1 : AbstractBase
where T2 : AbstractBase
{
public T1 Parent { get; protected set; }
public List<T2> Children = new List<T2>();
}
public class ItemA : BaseItem<ItemA, ItemB>
{
}
public class ItemB : BaseItem<ItemA, ItemC>
{
}
public class ItemC : BaseItem<ItemB, ItemD>
{
}
public class ItemD : BaseItem<ItemC, ItemD>
{
}
So two things. 1. Is this a good design? Is there a simpler/better way of doing this? I don't really like using a second abstract base class just to be able to use generics. 2. If i do keep this, what's the best way of handling the ends? (i.e ItemA does not have a parent in my actual problem domain, but it needs a parent to compile. ItemD does not have children, but i need to give it something)
Generic classes support an inheritance mechanism and can form hierarchies. Any generic class that takes a type T as a parameter can be inherited by another derived class. In this case, a parameter of type T is passed to the derived class.
A form of filial therapy, child-parent relationship theory (CPRT) teaches parents to use child-centered play therapy (CCPT) skills with their children. Based on attachment theory, CPRT espouses that a secure bond between parent and child is mandatory for children's healthy development.
The Parent-Child Relationship is one that nurtures the physical, emotional and social development of the child. It is a unique bond that every child and parent will can enjoy and nurture. This relationship lays the foundation for the child's personality, life choices and overall behaviour.
Also known as a document family.
If I understand you right, you are saying that ItemA
never has a parent and ItemD
never has any children, right? To be honest, I would probably just declare the separate classes with their own parent/children properties of the right type:
public abstract class AbstractBase
{
public abstract string Function1();
}
public class ItemA : AbstractBase
{
public List<ItemB> Children = new List<ItemB>();
}
public class ItemB : AbstractBase
{
public ItemA Parent { get; protected set; }
public List<ItemC> Children = new List<ItemC>();
}
public class ItemC : AbstractBase
{
public ItemB Parent { get; protected set; }
public List<ItemD> Children = new List<ItemD>();
}
public class ItemD : AbstractBase
{
public ItemC Parent { get; protected set; }
}
The only thing you are repeating here is the Parent
and Children
property/field. All the other common functionality you can implement in the AbstractBase
. (Unless, of course, that functionality needs access to the parents/children — but then you’re back to square one even in your solution.)
I would do it like this:
public interface IChildOf<T> {
T Parent { get; set; }
}
public interface IParent<T> {
List<T> Children { get; set; }
}
//This class handles all of the cases that have both parent and children
public abstract class BaseItem<T1, T2> : IParent<T1>, IChildOf<T2>
{
public List<T1> Children { get; set; }
public T2 Parent { get; set; }
}
//This class handles the top level parent
public class ItemA : IParent<ItemB>
{
public List<ItemB> Children { get; set; }
}
public class ItemB : BaseItem<ItemC, ItemA>
{
}
public class ItemC : BaseItem<ItemD, ItemB>
{
}
//.... as many intermediates as you like.
//This class handles the bottom level items with no children
public class ItemD : IChildOf<ItemC>
{
public ItemC Parent { get; set; }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With