Object-oriented – When to stop inheritance

design-patternsdesign-principlesobject-orientedprogramming practices

Once upon time ago I asked a question on Stack Overflow about inheritance.

I have said I design chess engine in OOP fashion. So I inherit all my pieces from Piece abstract class but inheritance still goes. Let me show by code

public abstract class Piece
{
    public void MakeMove();
    public void TakeBackMove();
}

public abstract class Pawn: Piece {}

public class WhitePawn :Pawn {}

public class BlackPawn:Pawn {}

Programmers has been found my design a little bit over engineering and suggested to remove colored piece classes and hold piece color as a property member like below.

public abstract class Piece
{
    public Color Color { get; set; }
    public abstract void MakeMove();
    public abstract void TakeBackMove();
}

In this way Piece can know his color. After implementation i have seen my implementation goes like below.

public abstract class Pawn: Piece
{
    public override void MakeMove()
    {
        if (this.Color == Color.White)
        {

        }
        else
        {

        }
    }

    public override void TakeBackMove()
    {
        if (this.Color == Color.White)
        {

        }
        else
        {

        }
    }
}

Now I see that keep color property causing if statements in implementations. It makes me feel we need specific color pieces in inheritance hierarchy.

In such a case would you have classes like WhitePawn, BlackPawn or would you go to design by keeping Color property?

Without seen such a problem how would you want to start design? Keep Color property or having inheritance solution ?

Edit: I want to specify that my example may not completely match real life example. So before try to guess implementation details just concentrate the question.

I actually simply asking if using Color property will cause if statements better to use inheritance ?

Best Answer

Imagine you design an application which contains vehicles. Do you create something like this?

class BlackVehicle : Vehicle { }
class DarkBlueVehicle : Vehicle { }
class DarkGreenVehicle : Vehicle { }
// hundreds of other classes...

In real life, color is a property of an object (either a car or a chess piece), and must be represented by a property.

Are MakeMove and TakeBackMove different for blacks and whites? Not at all: the rules are the same for both players, which means that those two methods will be exactly the same for blacks and whites, which means that you are adding a condition where you don't need it.

On the other hand, if you have WhitePawn and BlackPawn, I will not be surprised if soon or later you'll write:

var piece = (Pawn)this.CurrentPiece;
if (piece is WhitePawn)
{
}
else // The pice is of type BlackPawn
{
}

or even something like:

public abstract class Pawn
{
    public Color Player
    {
        get
        {
            return this is WhitePawn ? Color.White : Color.Black;
        }
    }
}

// Now imagine doing the same thing for every other piece.
Related Topic