I'm trying to remove the redundancy I have in my Enemy0
, Enemy1
, ... classes that inherit from my abstract Enemy
class. This is all Monogame/XNA.
My abstract class looks like so:
public abstract class Enemy
{
public abstract Vector2 Position { get; }
public Enemy() {}
public abstract void Update(GameTime gameTime);
public abstract void Draw(SpriteBatch spriteBatch);
public abstract Part getLeftPart();
public abstract Part getRightPart();
public abstract Part getLeftLeftPart(); //This method only used in Boss0 classes
public abstract Part getRightRightPart(); //This method only used in Boss0 classes
}
Though my Enemy#
classes vary in implementation, some methods are exactly the same/redundant and take up room (but have parameters relative to that class, eg the private variable _leftPartPos
).
The problem occurs when I have 20 or so Enemy#
classes and I decide to add an extra parameter to the Part
object (which is used in getLeftPart()
- I would have to also modify 20 of those classes that inherit the Enemy
public class Enemy0 : Enemy
{
private Texture2D _partTexture;
private Vector2 _leftpartPos;
private Vector2 _rightPartPos;
public override Vector2 Position
{
get { return _position; } // Reason for this get is to access inner variables
} // like _position.X = 10
private Vector2 _position;
public Enemy() {}
public abstract void Update(GameTime gameTime)
{
// Some varying functionality per inheriting class
}
public abstract void Draw(SpriteBatch spriteBatch)
{
// Some varying functionality per inheriting class
}
public override Part getLeftPart() // This always returns the same object (with
{ // different params)
return new Part(
_partTexture,
_leftPartPos,
SpriteEffects.FlipHorizontally);
}
public abstract Part getRightPart()
{
return new Part(
_partTexture,
_rightPartPos,
SpriteEffects.None);
}
public override Part getLeftLeftPart()
{
return null; // This only returns an instance in Boss0, Boss1, etc
}
public override Part getRightRightPart()
{
return null;
}
}
The reason I have this abstract class is so that I can initialize a List<Enemy>
object and access its varied methods without having to cast each class as Enemy0
, Enemy1
, ...
Is there a way I can throw in the functionality of getLeftPart()
, getRightPart()
, ... into my abstract class? Is there a better approach for all this?
Declare them as virtual
instead of abstract
. That way you can provide a base implementation in the root class and override it in the child classes if they require different functionality.
public abstract class RootClass
{
public virtual void DoSomething()
{
Console.WriteLine("I'm doing something in the root class");
}
}
public class ChildClass1 : RootClass
{
public void SomethingElse()
{
DoSomething(); //Prints out "I'm doing something in the root class"
}
}
public class ChildClass2 : RootClass
{
public void SomethingElse()
{
DoSomething(); //Prints out "I'm doing something in ChildClass2
}
public override void DoSomething()
{
Console.WriteLine("I'm doing something in ChildClass2");
}
}
If you have to take variable numbers of parameters, declare the method with the params
attribute, like:
public virtual void DoSomething(params object[] args)
This causes boxing, so be aware of the performance implications. If you need to do something more specific, try:
public virtual void DoSomething<T>(params T[] args)
But the only difference here is that all the parameters must be of the same type, or convertible to that type. If you only need one parameter of some type, use:
public virtual void DoSomething<T>(T arg)
or you can have two (or more types)
public virtual void DoSomething<T1, T2>(T1 arg1, T2 arg2)
etc, etc.