Отказ от ответственности: я не смог четко описать, что именно я пытаюсь сделать, поэтому я надеюсь, что пример будет более ясным, чем мое объяснение! Пожалуйста, предложите любую повторную фразу, чтобы сделать ее более ясной. :)Методы перегрузки для реализации особых случаев интерфейса
Можно ли переопределить функции с более конкретными версиями, чем те, которые требуются интерфейс для того, чтобы справиться с подклассы параметров методов в этом интерфейсе отдельно в общем случае? (Пример и лучшее объяснение ниже ...) Если это невозможно сделать напрямую, есть ли какой-то шаблон, который можно использовать для достижения аналогичного эффекта?
Пример
#include <iostream>
class BaseNode {};
class DerivedNode : public BaseNode {};
class NodeProcessingInterface
{
public:
virtual void processNode(BaseNode* node) = 0;
};
class MyNodeProcessor : public NodeProcessingInterface
{
public:
virtual void processNode(BaseNode* node)
{
std::cout << "Processing a node." << std::endl;
}
virtual void processNode(DerivedNode* node)
{
std::cout << "Special processing for a DerivedNode." << std::endl;
}
};
int main()
{
BaseNode* bn = new BaseNode();
DerivedNode* dn = new DerivedNode();
NodeProcessingInterface* processor = new MyNodeProcessor();
// Calls MyNodeProcessor::processNode(BaseNode) as expected.
processor->processNode(bn);
// Calls MyNodeProcessor::processNode(BaseNode).
// I would like this to call MyNodeProcessor::processNode(DerivedNode).
processor->processNode(dn);
delete bn;
delete dn;
delete processor;
return 0;
}
Моя мотивация
Я хочу, чтобы иметь возможность реализовать несколько различных бетонных NodeProcessor
s некоторые из которых будут относиться ко всем узлам одинаковы (т.е. реализовать только то, что показано в интерфейсе) и некоторые из них будут различать разные типы узлов (как в MyNodeProcessor
). Поэтому я хотел бы, чтобы второй вызов processNode(dn)
использовал реализацию в MyNodeProcessor::processNode(DerivedNode)
путем перегрузки (некоторые части/подклассы) методов интерфейса. Это возможно?
Очевидно, что если я изменю processor
на тип MyNodeProcessor*
, тогда это работает так, как ожидалось, но мне нужно иметь возможность использовать разные процессоры узлов взаимозаменяемо.
Я также могу обойти это, имея один метод processNode(BaseNode)
, который проверяет точный тип его аргумента во время выполнения и ветви на основе этого. Мне кажется нецелесообразным включать эту проверку в мой код (особенно, когда число типов узлов растет, и у меня есть гигантский оператор switch). Я чувствую, что язык должен быть в состоянии помочь.
Я использую C++, но я заинтересован в общих ответов, а если вы предпочитаете (или, если это проще/отличается на других языках).
Вы посмотрели шаблон посетителя? –
Это называется проблемой «двойной отправки» http://stackoverflow.com/questions/tagged/double-dispatch –
На самом деле, мое приложение использует шаблон посетителя, где я бы хотел, чтобы разные посетители посещали узлы с разными уровнями зернистость. То есть, один посетитель будет обрабатывать все узлы одинаково, в то время как другой будет обрабатывать все узлы по-разному, а другой может рассматривать некоторые типы узлов как общие, но включать специальную обработку некоторых других типов узлов. Я удалил все ссылки на это при создании моего MWE, поскольку это все еще кажется ядром проблемы. – Ben