I have an interface (defined as a abstract base class) that looks like this:
class AbstractInterface
{
public:
bool IsRelatedTo(const AbstractInterface& other) const = 0;
}
And I have an implementation of this (constructors etc omitted):
class ConcreteThing
{
public:
bool IsRelatedTo(const AbstractInterface& other) const
{
return m_ImplObject.has_relationship_to(other.m_ImplObject);
}
private:
ImplementationObject m_ImplObject;
}
The AbstractInterface forms an interface in Project A, and the ConcreteThing lives in Project B as an implementation of that interface. This is so that code in Project A can access data from Project B without having a direct dependency on it - Project B just has to implement the correct interface.
Obviously the line in the body of the IsRelatedTo function cannot compile - that instance of ConcreteThing has an m_ImplObject member, but it can't assume that all AbstractInterfaces do, including the other argument.
In my system, I can actually assume that all implementations of AbstractInterface are instances of ConcreteThing (or subclasses thereof), but I'd prefer not to be casting the object to the concrete type in order to get at the private member, or encoding that assumption in a way that will crash without a diagnostic later if this assumption ceases to hold true.
I cannot modify ImplementationObject, but I can modify AbstractInterface and ConcreteThing. I also cannot use the standard RTTI mechanism for checking a type prior to casting, or use dynamic_cast for a similar purpose.
I have a feeling that I might be able to overload IsRelatedTo with a ConcreteThing argument, but I'm not sure how to call it via the base IsRelatedTo(AbstractInterface) method. It wouldn't get called automatically as it's not a strict reimplementation of that method.
Is there a pattern for doing what I want here, allowing me to implement the IsRelatedTo function via ImplementationObject::has_relationship_to(ImplementationObject), without risky casts?
(Also, I couldn't think of a good question title - please change it if you have a better one.)