tło
Oto faktyczny problem, nad którym pracuję: chcę sposób na reprezentowanie kart w grze karcianej Magic: The Gathering . Większość kart w grze to normalnie wyglądające karty, ale niektóre z nich są podzielone na dwie części, każda z własną nazwą. Każda połowa tych dwuczęściowych kart jest traktowana jak karta. Dla jasności użyję Cardtylko odniesienia do czegoś, co jest albo zwykłą kartą, albo połową dwuczęściowej karty (innymi słowy, czymś o tylko jednej nazwie).

Mamy więc typ podstawowy, Card. Celem tych obiektów jest po prostu zachowanie właściwości karty. Tak naprawdę nic nie robią.
interface Card {
String name();
String text();
// etc
}
Istnieją dwie podklasy Card, które nazywam PartialCard(połowa dwuczęściowej karty) i WholeCard(zwykła karta). PartialCardma dwie dodatkowe metody: PartialCard otherPart()i boolean isFirstPart().
Przedstawiciele
Jeśli mam talię, powinna ona składać się z WholeCards, a nie Cards, ponieważ Cardmoże to być a PartialCard, i to nie miałoby sensu. Chcę więc obiektu reprezentującego „fizyczną kartę”, czyli coś, co może reprezentować jeden WholeCardlub dwa PartialCards. Wstępnie nazywam ten typ Representativei Cardmam metodę getRepresentative(). A Representativenie podałby prawie żadnych bezpośrednich informacji na temat karty, którą reprezentuje, wskazywałby tylko na niego / nich. Teraz moim genialnym / szalonym / głupim pomysłem (ty decydujesz) jest to, że WholeCard dziedziczy po obu Card i Representative. W końcu są to karty, które przedstawiają się! WholeCards mogą implementować getRepresentativejako return this;.
Jeśli chodzi o PartialCards, nie reprezentują siebie, ale mają zewnętrzny, Representativektóry nie jest Card, ale zapewnia metody dostępu do dwóch PartialCard.
Myślę, że ta hierarchia typów ma sens, ale jest skomplikowana. Jeśli myślimy o Card„kartach pojęciowych” i Representative„kartach fizycznych”, cóż, większość kart to oba! Myślę, że można argumentować, że karty fizyczne faktycznie zawierają karty koncepcyjne i że to nie to samo , ale twierdzę, że tak.
Konieczność odlewania typu
Ponieważ PartialCards i WholeCardsoba są Card, i zwykle nie ma dobrego powodu, aby je rozdzielić, normalnie po prostu pracowałbym Collection<Card>. Czasami więc musiałbym przesyłać PartialCard, aby uzyskać dostęp do ich dodatkowych metod. Obecnie używam opisanego tutaj systemu, ponieważ tak naprawdę nie lubię jawnych rzutów. I tak Card, Representativetrzeba by rzucić na albo, WholeCardalbo Composite, aby uzyskać dostęp do rzeczywistych Cards, które reprezentują.
Podsumowując:
- Typ podstawowy
Representative - Typ podstawowy
Card - Wpisz
WholeCard extends Card, Representative(nie wymaga dostępu, reprezentuje się) - Typ
PartialCard extends Card(daje dostęp do innej części) - Typ
Composite extends Representative(daje dostęp do obu części)
Czy to jest szalone? Myślę, że to naprawdę ma sens, ale szczerze mówiąc, nie jestem pewien.