Uma pesquisa rápida dessa troca de pilha mostra que, em geral, a composição é geralmente considerada mais flexível que a herança, mas, como sempre, depende do projeto etc., e há momentos em que a herança é a melhor escolha. Quero fazer um jogo de xadrez 3D em que cada peça tenha uma malha, possivelmente animações diferentes e assim por diante. Neste exemplo concreto, parece que você poderia argumentar sobre as duas abordagens. Estou errado?
A herança seria algo parecido com isto (com construtor adequado, etc.)
class BasePiece
{
virtual Squares GetValidMoveSquares() = 0;
Mesh* mesh;
// Other fields
}
class Pawn : public BasePiece
{
Squares GetValidMoveSquares() override;
}
que certamente obedece ao princípio "é-a", enquanto a composição se pareceria com isso
class MovementComponent
{
virtual Squares GetValidMoveSquares() = 0;
}
class PawnMovementComponent
{
Squares GetValidMoveSquares() override;
}
enum class Type
{
PAWN,
BISHOP, //etc
}
class Piece
{
MovementComponent* movementComponent;
MeshComponent* mesh;
Type type;
// Other fields
}
É mais uma questão de preferência pessoal ou uma abordagem é claramente uma escolha mais inteligente do que a outra aqui?
EDIT: Eu acho que aprendi algo com cada resposta, então me sinto mal por escolher apenas uma. Minha solução final se inspirará em vários dos posts aqui (ainda trabalhando nisso). Obrigado a todos que tiveram tempo para responder.
var Pawn = new Piece(howIMove, howITake, whatILookLike)
parece muito mais simples, mais gerenciável e mais sustentável para mim do que uma hierarquia de herança.