Скажем, у меня есть class Action
, который хранит некоторые Guy
с и вовлекает их в действие через некоторое время:
class Action {
std::vector<Guy> guys;
void bring() {
Guy newcomer = guys.back();
switch (newcomer.characteristic) {
// see below
}
}
// ...
};
Вот проблема с этим switch
: у парня может быть черта, которая может нуждаться в каком-либо дополнительном объяснении или может не нуждаться ни в каком. Например:
case loser: // no more information needed to continue
banish(guy);
break;
case buddy:
Guy buddy = newcomer.whose(); // the "explanation" which is needed for this case
if (is_here(buddy)) {
newcomer.happiness += 42;
}
Как я могу разумно хранить информацию, которая может понадобиться? К сожалению, у него могут быть разные типы (с точки зрения языка программирования), поэтому предоставление членов класса для каждого возможного перечислителя не представляется хорошо масштабируемым вариантом и подвержено ошибкам из-за простоты совершения неподходящих вызовов:
enum Characteristic { // isn't "enum class" for brevity of the example
buddy, gourmet, loser, // etc.
};
class Guy {
public:
Characteristic characteristic;
Guy whose() {
if (characteristic != buddy) {
throw std::logic_error("inappropriate call"); // awful!
}
return this->buddy;
}
Food favorite() { // for "gourmet"
// same as above?!
}
// etc.
};
Я думал о наследовании, но ничего не придумал. Лучшая идея выглядит как
void Derived_guy::be_brought(Action& action) {
// modify action in any way
}
Однако для того, чтобы узнать Action
, что является старшей абстракцией - плохой дизайн, требуется Guy
.
Как еще можно решить мою проблему?