I was doing some reading on the weekend and came across some really good thoughts on how to make decisions in code – but not by using conventional if or select branching mechanisms or others that masquerade as flow control statements under other guises.
There’s a whole movement for “if-less programming”.
And it fits very well with using OOP and the capabilities of polymorphism in ways that make your code clearer and easier to maintain and extend.
Let’s say you have a class that represents vehicles. Your program permits you to have many types of vehicles with various capabilities. And somewhere in that class that represents a vehicle you might have code like :
Function calculateMaximumWeightCapacity() as Double if ( vehicleType = "Transport" ) then // we have to account for the fact this has 18 wheels and 5 axles elseif ( vehicleType = "Truck" ) then // we have to account for what kind of light duty truck this is elseif ( vehicleType = "Car" ) then // we have to account for what kind of car this is as a mini cant // carry as much as a impala end if End Function
Yes this is contrived but you get the point
IF you have classes that display this kind of code then you probably should consider using polymorphism in a way it can make you life easier.
In your application, if you have this kind of code, then EVERY time you want to add a new kind of vehicle you have code to adjust. You’ll need to update every possible place this kind of selection goes on. And if you miss one you have bugs.
If However we used polymorphism to help us we could be sure that any time we added a new vehicle type we definitely covered all the required functionality AND that we didnt have to adjust a lot of code in many places.(1)
Instead if we had
Class Vehicle Private Sub Constructor() // this is so we make this class "abstract" and // you cannot create new vehicles - you MUST create // instances of subclasses only End Sub Function calculateMaximumWeightCapacity() as Double // since we have NO way to FORCE a subclass to override this // we put a break in here so we can figure out which subclass // did NOT override this BREAK End Function End Class Class Transport Inherits Vehicle Function calculateMaximumWeightCapacity() as Double // we have to account for the fact this has 18 wheels and 5 axles return 30000 // just for fun ! End Function End Class Class Car Inherits Vehicle End Class Class Mini Inherits Car Function calculateMaximumWeightCapacity() as Double // we have to account for what kind of car this is as a mini cant // carry as much as a impala return 500 End Function End Class Class Impala Inherits Car Function calculateMaximumWeightCapacity() as Double // we have to account for what kind of car this is as a mini cant // carry as much as a impala return 1000 End Function End Class .. and so on ...
And this gets rid of the need to use an IF to test what kind of vehicle it is to determine how to compute the weight. The specific subclass just does it knowing that its a transport, a truck, a mini or an impala.
Function calculateMaximumWeightCapacity() as Double return self.calculateMaximumWeightCapacity() End Function
Note that this code is much simpler to follow.
And when you need to add a new kind of vehicle you add a new class type, recompile and off your program goes because you havent had to hunt around and find all the places where you need to check vehicle types and maybe introduce new bugs.
Polymorphism is definitely your friend here.
(1) there are some things that Xojo does NOT provide that would make life simpler. A means of forcing a subclass to override a specific method defined in a super class does NOT exist. IF we use a base class we can only catch that a subclass has not overridden a method. Some languages have a means for a base class to define a method that subclasses MUST implement. Xojo does not.
Its possible to use an interface to force implementors of an interface to implement a method BUT this MAY be the wrong approach for the specific problem.