I have a series of shape objects that can check if they intersect one another (an intersection is true if any part of either object overlaps the other). This works great with double dispatch because the intersection of two objects can be represented relative to either object and still be valid and true.
I recently added (read as: "attempted to add") a Contains method that tests whether or not a shape completely encloses another. The double dispatch fails because two shapes of differing sizes will work for Intersect but not Contains: shape_one
is a big circle, and shape_two
is a smaller circle completely enclosed by shape_one
. The call shape_one.Contains(shape_two)
will return true but shape_two.Contains(shape_one)
will return false.
Is there a way to implement double dispatch for this type of scenario?
(Title edits are encouraged to increase comprehension of question...)
A sample of the Intersects methods with double dispatch:
bool Rectangle::Intersects(const Shape& shape) const {
return shape.Intersects(*this);
}
bool Rectangle::Intersects(const Point& point) const {
return point.Intersects(*this);
}
bool Rectangle::Intersects(const Line& line) const {
return line.Intersects(*this);
}
bool Rectangle::Intersects(const Rectangle& rectangle) const {
double myTop = this->GetY();
double myLeft = this->GetX();
double myRight = myLeft + this->GetWidth();
double myBottom = myTop + this->GetHeight();
double rTop = rectangle.GetY();
double rLeft = rectangle.GetX();
double rRight = rLeft + rectangle.GetWidth();
double rBottom = rTop + rectangle.GetHeight();
if(myTop > rBottom) return false;
if(myBottom < rTop) return false;
if(myLeft > rRight) return false;
if(myRight < rLeft) return false;
return true;
}
A sample of the Contains methods with double dispatch:
//THIS RESULTS IN A STACK OVERFLOW! DUE TO INFINITE RECURSION!
bool Rectangle::Contains(const Shape& shape) const {
return this->Contains(shape);
}
//THIS IS NOT TRUE IN ALL CASES!
bool Rectangle::Contains(const Shape& shape) const {
return shape.Contains(*this);
}
bool Rectangle::Contains(const Point& point) const {
return this->Intersects(point);
}
bool Rectangle::Contains(const Line& line) const {
return this->Intersects(line.GetPointOne()) && this->Intersects(line.GetPointTwo());
}
bool Rectangle::Contains(const Rectangle& rectangle) const {
return this->Intersects(rectangle.GetTopLeft()) && this->Intersects(rectangle.GetTopRight()) && this->Intersects(rectangle.GetBottomLeft()) && this->Intersects(rectangle.GetBottomRight());
}