Não tem jeito certo, tudo depende do problema específico que vc quer resolver.
Uma ideia inicial (que já sugeriram) é criar classes para cada espécie (classe Gato
, Leopardo
, Tigre
, etc), sendo que todas herdam da classe Felino
. Aí Felino
teria os atributos x
e y
, e as subclasses teriam o z
.
Mas nada impede que se tenha apenas uma classe Felino
com os atributos x
, y
e z
, e mais um atributo extra para designar a espécie. O que é melhor? Depende. Sem os requisitos, não dá pra saber - e este costuma ser o limitante de muitas apostilas, pois geralmente elas se focam no mecanismo e não vão além disso (ou seja, não explicam os casos reais, vantagens e desvantagens de cada abordagem, etc).
Por exemplo, se a ideia é ter um software de taxonomia, que possua todas as categorias existentes (reino, filo, classe, ordem, etc). Será que vale a pena criar classes e subclasses pra cada coisa? Eu acho que não, pois existem milhões de espécies, divididas em milhares de gêneros, famílias, ordens, etc. Criar uma hierarquia com milhares/milhões de classes é uma insanidade, sem contar que cada vez que uma espécie nova fosse descoberta, vc teria que criar uma nova classe.
Neste caso seria melhor ter uma única classe SerVivo
, que possua os atributos reino
, filo
, classe
, etc. Os reinos podem até ser um enum
, por exemplo, já que são poucos. Quando existem mais valores possíveis (50? 100?) e que não mudam com tanta frequência, poderia ser um array fixo de strings, e o valor do campo é o índice do array. E quando existem milhares ou milhões de possibilidades, aí o atributo é apenas uma string. E para características muito específicas, poderia ter um Map
genérico contendo vários pares de "nome/valor".
Agora se vc só quer modelar meia dúzia de felinos para um problema pequeno e específico, talvez não faça tanta diferença usar herança ou composição. Mas ainda sim precisaria avaliar os requisitos pra ter certeza.