fundo
Aqui está o problema real em que estou trabalhando: quero uma maneira de representar cartas no jogo de cartas Magic: The Gathering . A maioria das cartas do jogo são de aparência normal, mas algumas são divididas em duas partes, cada uma com seu próprio nome. Cada metade desses cartões de duas partes é tratada como um cartão em si. Portanto, para maior clareza, usarei Card
apenas para me referir a algo que é um cartão comum ou metade de um cartão de duas partes (em outras palavras, algo com apenas um nome).
Portanto, temos um tipo base, cartão. O objetivo desses objetos é realmente apenas manter as propriedades do cartão. Eles realmente não fazem nada sozinhos.
interface Card {
String name();
String text();
// etc
}
Existem duas subclasses de Card
que estou chamando PartialCard
(metade de um cartão de duas partes) e WholeCard
(um cartão comum). PartialCard
possui dois métodos adicionais: PartialCard otherPart()
e boolean isFirstPart()
.
Representantes
Se eu tiver um deck, ele deve ser composto por WholeCard
s, não Card
s, como Card
poderia ser um PartialCard
, e isso não faria sentido. Então, eu quero um objeto que represente um "cartão físico", ou seja, algo que possa representar um WholeCard
ou dois PartialCard
s. Estou provisoriamente chamando este tipo Representative
, e Card
teria o método getRepresentative()
. A Representative
forneceria quase nenhuma informação direta no (s) cartão (s) que representa, apenas apontaria para ele / eles. Agora, minha idéia brilhante / louca / burra (você decide) é que o WholeCard herda de ambos Card
e Representative
. Afinal, são cartões que se representam! WholeCards poderia implementar getRepresentative
como return this;
.
Quanto a PartialCards
, eles não se representam, mas eles têm um externo Representative
que não é um Card
, mas fornecem métodos para acessar os dois PartialCard
s.
Eu acho que essa hierarquia de tipos faz sentido, mas é complicado. Se pensarmos em Card
s como "cartões conceituais" Representative
es como "cartões físicos", bem, a maioria dos cartões é ambos! Eu acho que você poderia argumentar que os cartões físicos contêm de fato cartões conceituais e que eles não são a mesma coisa , mas eu argumentaria que eles são.
Necessidade de fundição
Como PartialCard
s e WholeCards
são ambos Card
s, e geralmente não há uma boa razão para separá-los, normalmente eu apenas estaria trabalhando Collection<Card>
. Então, às vezes, eu precisaria converter PartialCard
s para acessar seus métodos adicionais. No momento, estou usando o sistema descrito aqui porque realmente não gosto de elencos explícitos. E como Card
, Representative
precisaria ser convertido para a WholeCard
ou Composite
para acessar os Card
s reais que eles representam.
Então, apenas para resumo:
- Tipo de base
Representative
- Tipo de base
Card
- Tipo
WholeCard extends Card, Representative
(não é necessário acesso, ele representa a si próprio) - Tipo
PartialCard extends Card
(dá acesso a outra parte) - Tipo
Composite extends Representative
(dá acesso às duas partes)
Isso é loucura? Acho que faz muito sentido, mas sinceramente não tenho certeza.