Фон
Вот настоящая проблема, над которой я работаю: я хочу представить карты в карточной игре Magic: The Gathering . Большинство карт в игре выглядят нормально, но некоторые из них разделены на две части, каждая со своим именем. Каждая половина этих двухкомпонентных карт рассматривается как сама карта. Поэтому для ясности я буду использовать Cardтолько для обозначения чего-то, что является либо обычной картой, либо половиной карты, состоящей из двух частей (другими словами, чем-то, имеющим только одно имя).

Итак, у нас есть базовый тип, карта. Цель этих объектов на самом деле просто держать свойства карты. Они на самом деле ничего не делают сами.
interface Card {
String name();
String text();
// etc
}
Есть два подкласса Card, которые я называю PartialCard(половина карты из двух частей) и WholeCard(обычная карта). PartialCardимеет два дополнительных метода: PartialCard otherPart()и boolean isFirstPart().
Представители
Если у меня есть колода, она должна состоять из WholeCards, а не Cards, поскольку a Cardможет быть a PartialCard, и это не имеет смысла. Поэтому я хочу, чтобы объект представлял «физическую карту», то есть что-то, что может представлять один WholeCardили два PartialCardэлемента s. Я предварительно вызываю этот тип Representative, и у Cardменя будет метод getRepresentative(). A Representativeпочти не предоставит прямой информации о картах, которые он представляет, он только укажет на нее / них. Теперь моя блестящая / сумасшедшая / глупая идея (вы решаете), что WholeCard наследует от обоих Card и Representative. В конце концов, это карты, которые представляют себя! WholeCards может реализовать getRepresentativeкак return this;.
Что касается PartialCards, они не представляют себя, но у них есть внешнее Representative, которое не является Card, но предоставляет методы для доступа к двум PartialCards.
Я думаю, что эта иерархия типов имеет смысл, но она сложная. Если мы рассматриваем Cards как «концептуальные карты», а Representatives как «физические карты», то большинство карт оба! Я думаю, вы могли бы поспорить, что физические карты на самом деле содержат концептуальные карты, и что это не одно и то же , но я бы сказал, что это так.
Необходимость литья типов
Поскольку PartialCards и WholeCardsесть оба Cards, и обычно нет веских причин для их разделения, я бы обычно просто работал с ними Collection<Card>. Поэтому иногда мне нужно приводить PartialCards, чтобы получить доступ к их дополнительным методам. Прямо сейчас я использую систему, описанную здесь, потому что я действительно не люблю явные приведения. И, как Card, Representativeбудет необходимо привести либо к WholeCardили Composite, чтобы получить доступ к фактическим Cards, которые они представляют.
Так что просто для резюме:
- Базовый тип
Representative - Базовый тип
Card - Тип
WholeCard extends Card, Representative(доступ не требуется, он представляет себя) - Тип
PartialCard extends Card(дает доступ к другой части) - Тип
Composite extends Representative(дает доступ к обеим частям)
Это безумие? Я думаю, что это действительно имеет большой смысл, но я, честно говоря, не уверен.