I have an object represented as a link / pointer to an interface. I would like to call a method on a specific object if this method is present, without changing the interface, breaking encapsulation, or writing any horrible hacks. How can I do that?
Here is an example.
I have an interface:
class IChatty { public: virtual ~IChatty() {}; virtual std::string Speak() const = 0; };
And a few specific implementations of this interface:
class SimpleChatty : public IChatty { public: ~SimpleChatty() {}; virtual std::string Speak() const override { return "hello"; } }; class SuperChatty : public IChatty { public: void AddToDictionary(const std::string& word) { words_.insert(word); } virtual std::string Speak() const override { std::string ret; for(auto w = words_.begin(); w != words_.end(); ++w ) { ret += *w; ret += " "; } return ret; } private: std::set<std::string> words_; };
The SuperChatty::AddToDictionary not present in the IChatty abstract interface, although it can be included in another new interface.
In the real world, these objects are built at the factory, concrete concrete instances of the abstract interface themselves. However, for our purposes, which are orthogonal to the problem under consideration:
int main() { IChatty* chatty = new SuperChatty; chatty->AddToDictionary("foo"); std::cout << chatty->Speak() << std::endl; }
Since AddToDictionary not part of the IChatty interface (and cannot be part of it), I can name it.
How can I call AddToDictionary in the chatty pointer without breaking encapsulation, writing some terrible hack, or accepting any other development shortcuts?
NOTE. In the real world, a dictionary is part of the SuperChatty object SuperChatty and cannot be separated from it.
NOTE2: I do not want to drag a specific type.