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ę Card
tylko 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). PartialCard
ma dwie dodatkowe metody: PartialCard otherPart()
i boolean isFirstPart()
.
Przedstawiciele
Jeśli mam talię, powinna ona składać się z WholeCard
s, a nie Card
s, ponieważ Card
moż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 WholeCard
lub dwa PartialCard
s. Wstępnie nazywam ten typ Representative
i Card
mam metodę getRepresentative()
. A Representative
nie 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ć getRepresentative
jako return this;
.
Jeśli chodzi o PartialCards
, nie reprezentują siebie, ale mają zewnętrzny, Representative
któ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ż PartialCard
s i WholeCards
oba 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
, Representative
trzeba by rzucić na albo, WholeCard
albo Composite
, aby uzyskać dostęp do rzeczywistych Card
s, 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.