I encountered a question today, found here, which raised this question for me.
Here's a pseudo-code example of what I'm getting at:
class Car{
public:
virtual int goFast() = 0;
};
class FordFocus : public Car {
public:
int goFast(){
return 35;
};
};
class Lamborghini : public Car {
bool roof;
public:
int goFast(){
return -1/0; // crash
};
void retractTheRoof(){
roof = 0;
};
};
class RichGuy {
vector<Car *> cars;
public:
void goDrive() {
for(int i = 0; i < cars.size(); ++i) {
if(Lamborghini* lambo = dynamic_cast<Lamborghini*>(cars[i])) {
lambo->retractTheRoof();
};
goFast();
};
};
};
In the example, there is a RichGuy
class. Richguy
only keeps track of his Cars
in a single vector. Because he has so many Cars
it would be too troublesome to keep track of them based on if they're a FordFocus
or a Lamborghini
. However, the only type of car he has with a retractable roof is the Lambo. In order to retractTheRoof()
, RichGuy
must now determine if the Car
he has is indeed a Lamboghini
, and then downcast to execute this function of it.
Based on this example, was the choice to downcast in good design? Or did it violate the purpose of polymorphism, assuming that purpose is to allow derived classes to define their own behavior, and provide a common interface for classes like RichGuy
? And if so, is there a better way to allow for functions like retractTheRoof()
(or at least it's effect) to be available to RichGuy
to use?