Contexte
Voici le problème réel sur lequel je travaille: je veux un moyen de représenter les cartes dans le jeu de cartes Magic: The Gathering . La plupart des cartes du jeu sont des cartes d'apparence normale, mais certaines d'entre elles sont divisées en deux parties, chacune avec son propre nom. Chaque moitié de ces cartes en deux parties est traitée comme une carte elle-même. Donc, pour plus de clarté, je vais utiliser Card
uniquement pour faire référence à quelque chose qui est soit une carte ordinaire, soit la moitié d'une carte en deux parties (en d'autres termes, quelque chose avec un seul nom).
Nous avons donc un type de base, Card. Le but de ces objets est vraiment juste de conserver les propriétés de la carte. Ils ne font vraiment rien par eux-mêmes.
interface Card {
String name();
String text();
// etc
}
Il y a deux sous-classes de Card
, que j'appelle PartialCard
(la moitié d'une carte en deux parties) et WholeCard
(une carte ordinaire). PartialCard
a deux méthodes supplémentaires: PartialCard otherPart()
et boolean isFirstPart()
.
Représentants
Si j'ai un deck, il devrait être composé de WholeCard
s, pas de Card
s, comme Card
pourrait être un PartialCard
, et cela n'aurait aucun sens. Je veux donc un objet qui représente une "carte physique", c'est-à-dire quelque chose qui puisse représenter un WholeCard
ou deux PartialCard
s. J'appelle provisoirement ce type Representative
et Card
j'aurais la méthode getRepresentative()
. A Representative
ne fournirait presque aucune information directe sur la ou les cartes qu'il représente, il ne ferait que les pointer. Maintenant, mon idée brillante / folle / stupide (vous décidez) est que WholeCard hérite des deux Card
et Representative
. Après tout, ce sont des cartes qui se représentent! WholeCards pourrait implémenter en getRepresentative
tant que return this;
.
Quant à PartialCards
, ils ne se représentent pas eux-mêmes, mais ils ont un externe Representative
qui n'est pas un Card
, mais fournit des méthodes pour accéder aux deux PartialCard
s.
Je pense que cette hiérarchie de types est logique, mais c'est compliqué. Si nous considérons Card
s comme des "cartes conceptuelles" et Representative
s comme des "cartes physiques", eh bien, la plupart des cartes sont les deux! Je pense que vous pourriez faire valoir que les cartes physiques contiennent en fait des cartes conceptuelles et qu'elles ne sont pas la même chose , mais je dirais qu'elles le sont.
Nécessité de coulée de caractères
Parce que PartialCard
s et WholeCards
sont tous les deux Card
s, et qu'il n'y a généralement aucune bonne raison de les séparer, je travaillerais normalement avec Collection<Card>
. Donc, parfois, je devais lancer des PartialCard
s pour accéder à leurs méthodes supplémentaires. En ce moment, j'utilise le système décrit ici parce que je n'aime vraiment pas les transtypages explicites. Et comme Card
, Representative
aurait besoin d'être converti en un WholeCard
ou Composite
pour accéder aux Card
s réels qu'ils représentent.
Donc, juste pour le résumé:
- Type de base
Representative
- Type de base
Card
- Type
WholeCard extends Card, Representative
(aucun accès requis, il se représente lui-même) - Type
PartialCard extends Card
(donne accès à une autre partie) - Type
Composite extends Representative
(donne accès aux deux parties)
Est-ce fou? Je pense que cela a beaucoup de sens, mais je ne suis honnêtement pas sûr.