Shape s[] = new Shape[0];
Class Shape should have methods such as draw(), size(), etc. The idea is that I would derive classes such as Square, Circle, etc from shape and be able to call these methods polymorphically. For instance:
for (int i=0; i < s.length; i++) {
s[i].draw();
}
This is what the Shape class in Processing looked like:
class Shape {
float x, y; // Center
float r; // radius
color c; // fill color
// Constructor
Shape (float x, float y, float r, color c) {
this.x = x; this.y = y; this.r = r; this.c = c;
}
// Draws the shape
void draw () {
}
}
Classes Circle and Square followed the same pattern, and the draw() method worked as expected. So far, so good. Problems started when I tried to add a method for shape intersection. It would have a signature such as:
// Returns true if and only if this shape intersects other
boolean intersects (Shape other) {
...
}
Notice that the method implements an operation between two shapes. It stands to reason that it would be possible to write methods in all derived classes implementing the particular intersection algorithm. For instance, Circle would have a method called
boolean intersects (Square other) ...
Thus, if s[i] is a circle and s[j] is a square, then the proper method would be automatically be called for s[i].intersects(s[j]), right? Well, it doesn't work that way. Class inheritance cannot be overloaded!
I then tried writing all variants explicitly in the base class, i.e.:
class Shape {
...
boolean intersects (Square other) ...
boolean intersects (Circle other) ...
...
}
Sorry. That doesn't work either. Late binding, which is the ability to select the proper method at run time does not work for selecting the proper method based on the argument signature. So, what's the solution? Answer: you have to test for the argument type yourself. Thus, method intersects for class Circle looks like:
}
Sorry. That doesn't work either. Late binding, which is the ability to select the proper method at run time does not work for selecting the proper method based on the argument signature. So, what's the solution? Answer: you have to test for the argument type yourself. Thus, method intersects for class Circle looks like:
// Returns true if and only if this shape intersects other
boolean intersects (Shape other) {
if (other instanceof Square) {
// Code for circle/square intersection
} else if (other instanceof Circle) {
// Code for circle/circle intersection
}
...
}
If I was writing a similar code in Python or Ruby, this is what I would have done from the start. This just goes to show how awkward and complicated language mechanisms based on explicitly declared types can get to no avail.
No comments:
Post a Comment