Во многих местах вы можете прочитать, что dynamic_cast
означает "плохой дизайн". Но я не могу найти статью с соответствующим использованием (показывая хороший дизайн, а не только "как использовать").
Я пишу настольную игру с доской и много разных типов карт, описанных со многими атрибутами (некоторые карты можно положить на доску). Поэтому я решил разбить его на следующие классы/интерфейсы:
class Card {};
class BoardCard : public Card {};
class ActionCard : public Card {};
// Other types of cards - but two are enough
class Deck {
Card* draw_card();
};
class Player {
void add_card(Card* card);
Card const* get_card();
};
class Board {
void put_card(BoardCard const*);
};
Некоторые ребята предположили, что я должен использовать только один класс, описывающий карту. Но я бы назвал много взаимоисключающих атрибутов. А в случае класса Board ' put_card(BoardCard const&)
- это часть интерфейса, в которую я не могу поместить какую-либо карточку на борт. Если бы у меня был только один тип карточек, я должен был бы проверить его внутри метода.
Я вижу поток следующим образом:
- общая карта находится в колоде (это не важно, каков ее тип)
- общая карта берется из колоды и передается игроку (так же, как указано выше)
- если игрок выбрал BoardCard, то его можно положить на доску
Поэтому я использую dynamic_cast
перед тем, как положить карту на доску. Я думаю, что использование какого-либо виртуального метода в этом случае не может быть и речи (кроме того, я бы не имел смысла добавлять какие-либо действия в отношении платы на каждую карту).
Поэтому мой вопрос: что я плохо разработал? Как я могу избежать dynamic_cast
? Использование некоторого атрибута типа, и if
бы это было лучшее решение...?
PS Любой источник, рассматривающий использование dynamic_cast
в контексте дизайна, более чем оценен.