Taking into account the accepted answer here, the idea for general recommendations is that, where possible, favor defining classes over interfaces.
Consider the following design:
- A base class
ChessPiece
, which multiple child classes are also defined - Some types of piece needs a record if they were already moved (namely
Pawn
,Rook
,King
): abool HasMoved
property - A type of piece, that being the
King
, cannot be captured; everything else can be: abool IsCaptured
property
The problem is the conflict between #2 and 3 (there's no problem if I implement only one of the two) because of the derived class King
, which is common in #2 and 3.
Ideally, both abstract classes CapturablePiece
and MoveRecordedPiece
, which both inherits from ChessPiece
, should be implemented. But C# doesn't allow for multiple class inheritance, and that's where interfaces come in.
If interfaces were implemented, now all concrete child classes can manually implement each required property. Consider then this example:
// needed type-check
ChessPiece piece;
// some calculations...
if (piece is ICapturablePiece) // or using the 'as' keyword
//or...
if (piece is IMoveRecordedPiece)
// which in the case of non-conflicting abstract classes,
// this is easily doable and valid because of
// inheritance to the base class
I cannot do this since interfaces are as-is. It cannot inherit from anything, it is just a standalone marker for methods that must be implemented.
The abstract class versions are still preferable - a CapturablePiece
and a MoveRecordedPiece
, since its base type is ChessPiece
, and I'm sure this logic is an "is-an" instead of a "can-do" (as mentioned in the link above).
My question now would be, how would I improve the design considering:
- The fact that you cannot inherit multiple classes, and interfaces cannot inherit anything.
- The favor of abstract classes over interfaces
- The code block where type-check is needed
EDIT:
This is not a duplicate of the linked question. This is more of a how to improve design while considering interfaces and abstract classes.