I'm running into an occasional design issue with classes, mostly in some video game stuff. The problem arises when a class that extends another class (such as a Player
) has a field that is also a class that has its own extended classes. I know this is a pattern issue but not sure how to resolve it properly.
Let's take a super simple example.
public class Engine {
public void Drive() {}
}
public class SpecialEngine : Engine {
public void Charge() {}
}
public class Car {
protected Engine engine;
public virtual void Move() {
this.engine.Drive();
}
}
public class SpecialCar : Car {
// Both SpecialCar.engine and SpecialCar.specialEngine
// would need to be set to an instance of SpecialEngine
private SpecialEngine specialEngine;
public override void Move() {
// or.. cast this.engine to SpecialEngine?
this.specialEngine.Charge();
base.Move();
}
}
Car
has an Engine
, and you can pass a SpecialEngine
to Car
(idk if C# uses the term "slicing" but this at least works in C++). But you cannot access any properties of SpecialEngine
. So you make SpecialCar
that could accept a SpecialEngine
as its engine
but you want to access SpecialEngine
, so you make a second field called specialEngine
and now have two references to it?
My thinking here is wrong and I'm not sure what I should do. I know I could have maybe a generic Car<T>
but I feel like I may end up with Car<A, B, C, D...>
.
C# supports Covariant returns. Just can use a single SpecialEngine
in SpecialCar
.
public class Engine
{
public void Drive() { }
}
public class SpecialEngine : Engine
{
public void Charge() { }
}
public class Car
{
protected virtual Engine Engine { get; }
public virtual void Move()
{
Engine.Drive();
}
}
public class SpecialCar : Car
{
protected override SpecialEngine Engine { get; }
public override void Move()
{
Engine.Charge();
base.Move();
}
}