July 26, 2008

Overrides and Shadows

Nice little inheritance tools there. I have no problem with them, except that I've had to shadow way to many methods on List and LinkedList for my combat tracker.

See, I need to know when my CreatureList (inherits List) and InitiativeList (inherits LinkedList) objects change. Neither base list type does - for that you have to use BindingList.

So I've been using not insubstantial, even if small, time shadowing (actually "new"-ing in C#, Shadows is the keyword from VB.NET) every add/remove method on those two classes to run the base's version and then fire off an event.

Which also leads me to post the following: the difference between overriding and shadowing.

When you override a function implemented by a base class, you change the function pointer for all instances of that derived class no matter what they look like to the outside world.


public class BaseClass
{
public override string ToString()
{
return "BaseClass";
}
}

public class InheritedClass : BaseClass
{
public override string ToString()
{
return "InheritedClass";
}
}

BaseClass testOne = new BaseClass();
//testOne.ToString() == "BaseClass"
InheritedClass testTwo = new InheritedClass();
//testTwo.ToString() == "InheritedClass"
BaseClass testThree = new InheritedClass();
//testThree.ToString() == "InheritedClass"


Shadows/new works differently. It only 'overrides' the function pointer if the inherited class is being used as the inherited class.


public class BaseClass
{
public override string ToString()
{
return "BaseClass";
}
}

public class InheritedClass : BaseClass
{
public new string ToString()
{
return "InheritedClass";
}
}

BaseClass testOne = new BaseClass();
//testOne.ToString() == "BaseClass"
InheritedClass testTwo = new InheritedClass();
//testTwo.ToString() == "InheritedClass"
BaseClass testThree = new InheritedClass();
//testThree.ToString() == "BaseClass"

2 comments:

Anonymous said...

Thanks for posting that! The whole "Shadows" thing has always been a bit confusing. Question: why not just inherit from BindingList?

Sam said...

CreatureList inherits from List because it allows sorting if the underlying values implement IComparable - which makes throwing a CreatureList into an InitiativeList a snap.

InitiativeList inherits from LinkedList because I need an explicit, not necessarily enumeratable, order to the list (I need to know who has the next turn, who had the last turn, etc. and I'd prefer to just track who has the current turn). Also, because it allows arbitrary insertion into the list through AddFirst, AddLast, AddBefore, and AddAfter. I need to be able to do that and still be able to find the next turn due to the ability to "Ready" an action or "Delay" your turn to another spot in the initiative order.

It should all make sense when I commit what I'm working on right now.