Object-Oriented Blog Process - VII

Inheritance.

The web shop example we've looked at so far is very simple, to put it lightly. Don't worry, I'll still keep it simple. But let us for a moment imagine a more realistic situation.

In our imagination a product class will have far more properties, like producer, supplier, cost price, product number, etc. Let's imagine we end up with at least 15 properties in our product class. Then let us agree that different types off products needs different properties as well. Golf ball objects need properties for radius, weight and number of dimples. Golf pants objects need properties for waist width, length, fabric and color.

What are our choises now? Do we add all properties we need to the product class. Then we'll have a bunch of unused properties on each object. And what if some product types have similar properties, but that have different methods and units of measurement. Sounds like this might grow into a monster of a class, with confusing logic for figuring out conflicting properties. Definitely  not a good option.

Then how about creating a class for each product type? Then we need to have all the 15 properties in all the classes. So if we need to add, change or delete a general property we have to do this in all different product classes. Not a good solution either, huh?

Inheritance to the rescue!

One of the key principles in Object-Oriented programing is inheritance, and it addresses exactly the kind of problem described above. The idea is that one class can have several child classes. In our case that means that we can keep our product class with all the (imagined) 15 properties in one place, and then have one child class called golfBalls and one child class called golfPants. These child classes will then inherit all the properties and methods from the parent class, and need just to worry about the properties and methods that are particularly for that product type. We can visualise this relationship in the following way:

You see that for simplicitys sake I've only kept the original two properties and associated methods for the product class. And I'm only dealing with two product types. One thing to note is that inheritance can go several levels deep (as many as you would need/wish). In our example we could have made a child class of products called cloths, with the fabric property, and then child classes of that one again for pants, shorts, shirts, skirts and caps. But for now we'll keep it simple and stick with to child classes with the product parent class.

Let's take a look at how our two new child classes look in ColdFusion code. As you'll see it's not much difference from the product class we created earlier. (I'm not including the setter and getter methods here, as they follow the same pattern as before - you can see the full code in the updated example application I'll post shortly)

<cfcomponent displayname="Golf Ball" extends="product" output="false">

 

 <!--- PROPERTIES --->
 <cfset variables.instance = StructNew() />

 <!--- INITIALIZATION / CONFIGURATION --->
 <cffunction name="init" access="public" returntype="golfball" output="false">
  <cfargument name="productName" type="string" required="false" default="" />
  <cfargument name="productPrice" type="numeric" required="false" default="" />
  <cfargument name="radius" type="numeric" required="false" default="" />
  <cfargument name="weight" type="numeric" required="false" default="" />
  <cfargument name="dimples" type="numeric" required="false" default="" />
  <cfscript>
   // run setters
   setRadius(arguments.radius);
   setWeight(arguments.weight);
   setDimples(arguments.dimples);
   super.init(argumentcollection=arguments);
   return this;
  </cfscript>
  </cffunction>

 <!--- METHODS --->

**** setter and getter methods go here ****

</cfcomponent>

 
<cfcomponent displayname="Golf Pants" extends="product" output="false">

 

 <!--- PROPERTIES --->
 <cfset variables.instance = StructNew() />

 <!--- INITIALIZATION / CONFIGURATION --->
 <cffunction name="init" access="public" returntype="golfpants" output="false">
  <cfargument name="productName" type="string" required="false" default="" />
  <cfargument name="productPrice" type="numeric" required="false" default="" />
  <cfargument name="waistWidth" type="numeric" required="false" default="" />
  <cfargument name="length" type="numeric" required="false" default="" />
  <cfargument name="fabric" type="string" required="false" default="" />
  <cfargument name="color" type="string" required="false" default="" />
  <cfscript>
   // run setters
   setWaistWidth(arguments.waistWidth);
   setLength(arguments.length);
   setFabric(arguments.fabric);
   setColor(arguments.color);
   super.init(argumentcollection=arguments);
   return this;
  </cfscript>
  </cffunction>

 <!--- METHODS --->

**** setter and getter methods go here ****

</cfcomponent>

The things to notice are the following. In the opening cfcomponent tag we're adding extends="product" to establish the inheritance. In the init() method we also have the cfarguments for the parent class. And lastly, still within the init method, we're calling a super.init() method. The super.init() method call the init() method of the parent class (also called super class). You also see that we are passing the arguments as a argumentcollection, rater than one and one as we did in earlier examples.So when creating a new object we now do something like this:

<cfset golfBall = createObject("component","golfball").init("Boyzoid Custom High-Speed","12.95","3","14","222") />
<cfset golfShorts = createObject("component","golfpants").init("Frank Shortser","9.50","32","30","Cotton","Green") />

My next post will be a download of a updated version of the example app, showing a working example of what I've just explained.

Comments