Extending inherited functions and properties

an article added by: Christian Roldan at 05222008


In: Root » » Programming » Extending inherited functions and properties

French Spanish Portuguese Italian German Japanese Chinese Korean Russian Arabic

We’ve said much regarding the theory of ColdFusion component inheritance, and frankly, much of it is seriously overblown. Inheritance shares its name with the object-oriented world, but that’s about all that it shares. CFC inheritance can be easily summed up with the following three simple statements:

One component can inherit from or extend another, after which the inheriting component can make use of its ancestor’s properties and methods.

If the inheriting component declares its own methods named differently from those in its ancestor, both the ancestor’s methods and the inheriting component’s methods can be called through the inheriting component. The same holds true for declaring properties by using names that do not match their ancestor’s.

If the inheriting component declares its own methods named the same as those in its ancestor, the inheriting component’s methods override the ancestor’s methods with the same name, as if the ancestor’s methods are hidden. The same holds true for declaring properties by using names that match their ancestor’s. Just keep these three simple principles in mind as you proceed through the following parts and don’t think that inheritance is any more complicated than this. Inheritance has a few applications in real-world ColdFusion development, but you’re likely to find that they are rare. Nevertheless, you should understand inheritance so that you can spot places in your application where it may be warranted.

You can use the package that you create in the codes to learn about extending components. Although we didn’t discuss it earlier, we created a property in the Emp component named empProperty, as follows:

<cfset This.empProperty = “Original Emp”>

Creating a variable in the This scope of the Emp component makes that variable a property of that component. Remember that all code in a component’s initialization area is executed once as an instance of the component is first created, which means that the empProperty property is automatically created and initialized to the value Original Emp as each instance of the Emp component is created. You can change the value of This.empProperty after it is initialized, and each instance of the Emp component may contain its own value of empProperty. If you inherit or extend a component, the functions and properties of the ancestor are, in essence, copied into the inheritor, where they can be called and used just as if they were a part of the inheritor. So, if you create a component named Manager that extends the Emp component, as shown in the code, the Manager component also contains a property named empProperty. Manager extends Emp, so Manager inherits Emp’s properties and functions.

<cfcomponent extends=”com.herdomain.calcbonus.Emp”>
   <cfset This.managersOwnProperty = “Just for us Managers”>
   <cffunction name=”ManagerBonus”
   access=”public”
   returntype=”numeric”>
   <cfargument name=”SSN”
   type=”string”
   required=”yes”>
   <cfreturn Bonus(Arguments.SSN) * 1.15>
   </cffunction>
 </cfcomponent>

Notice also that the preceding code declares a property directly in Manager, named managersOwnProperty. Manager inherits Emp’s properties, but the process is a one-way street, so managersOwnProperty is available only in the Manager component and, not in the Emp component. The same principles of inheritance that work for component properties also work for component functions. The Emp component contains a Bonus() function that calculates the bonuses of nonmanagerial employees, but managers make an additional 15 percent bonus. To calculate manager bonuses, you extend Manager’s functionality by declaring a function named ManagerBonus(), as shown in the codes. To retrieve the normal bonus for an employee, ManagerBonus() must call the Bonus() function that is declared in the Emp component. But Manager extends Emp, so Bonus() is available as one of Manager’s own functions; all ManagerBonus() must do is return Bonus() multiplied by 1.15, as follows:

<cfreturn Bonus(Arguments.SSN) * 1.15>

The code shows inheritance in action. Notice how the properties and functions of both Emp and Manager are directly accessible from Manager.

<cfscript>
   managerServices = CreateObject(“Component”,
   “com.herdomain.calcbonus.Manager”);
   </cfscript>
   <cfoutput>
   <p>These are all accessed through the Manager component only:</p>
   <p>Manager Bonus:
   <b>#managerServices.ManagerBonus(“012-34-5678”)#</b><br>
   managersOwnProperty:
   <b>#managerServices.managersOwnProperty#</b></p>
   <p>Standard Bonus:
   <b>#managerServices.Bonus(“012-34-5678”)#</b><br>
   empProperty:
   <b>#managerServices.empProperty#</b></p>
 </cfoutput>

Everything that you’ve done so far is known as extending because you leave all the functionality of the ancestor component unmodified and extend it only by adding new functions and properties. In the object-oriented world, this technique is known as specialization: A manager is a specialized employee who does the same basic things plus a few more. To use a couple more object-oriented terms, a manager is a subtype of an employee, and the employee is the supertype of the manager. Don’t get hung up on these terms; we mention them here only so that you can follow along in the inevitable discussions that you hear in comparing components to objects.

Overriding replaces inherited properties and functions with something completely different from what was inherited. To override a function or property, simply declare a function or property of the same name in the inheritor component. It’s as simple as that. The code shows overriding in action. The company that manufactured Stan Cox’s telephone —Fooster—turns out to be scamming everyone. Through creative trading contracts with various “hot-talk” services and bundling service options with Fooster’s Model ADHCC (AutoDial Hot ColdFusion Chicks) Telephone, Fooster alleged nonexistent profits that made its stock price soar sky-high and attract investors. The money started pouring in, so the company had to find something to do with it. The answer: employee bonuses.

<cfcomponent extends=”com.herdomain.calcbonus.Emp”>
   <cfset This.empProperty = “Fooster Override Emp”>
   <cfset This.foostersOwnProperty = “Just for Fooster”>
   <cffunction name=”Bonus”
   access=”public”
   returntype=”numeric”>
   <cfargument name=”SSN”
   type=”string”
   required=”yes”>
   <cfreturn XmasBonus(Arguments.SSN) + 113000000>
   </cffunction>
 </cfcomponent>

So if you are a Fooster employee, your total annual bonus is your Christmas bonus plus 113 million dollars. Sweet! By declaring its own Bonus() function, the Fooster component overrides the Bonus() function inherited from the Employee component, but the inherited XmasBonus() function is still available because it wasn’t overridden. The code shows Fooster’s bonus system in action.

<cfscript>
   embezzlerServices = CreateObject(“Component”,
   “com.herdomain.calcbonus.Fooster”);
   </cfscript>
   <cfoutput>
   <p>These are all accessed through the Fooster component only:</p>
   <p>Standard Bonus, Fooster-style:
   <b>#embezzlerServices.Bonus(“012-34-5678”)#</b><br>
   empProperty:
   <b>#embezzlerServices.empProperty#</b><br>
   foostersOwnProperty:
   <b>#embezzlerServices.foostersOwnProperty#</b></p>
 </cfoutput>

Do you see how straightforward ColdFusion component inheritance is? The rules are simple: Ancestor functions and properties are available in the inheritor unless overridden. These examples are, by necessity, very brief. Real-world implementations of component overriding are the result of very careful component planning and design, because they must take into consideration the complete set of behaviors of each component type and its extended subtypes. Try to do that with some category of things in nature, like aircraft or guns, and you quickly see how this is not a trivial matter.

You’ve learned quite a lot about components in this article. Not only did you see one being built from the ground up, you followed the very structure of how they are built so you could get a better feel for how to use them. You learned how component functions are often referred to as methods, how methods can be either class methods or instance methods depending on how the component that declares them is used, and how these principles are similar to object oriented development. You’ve also learned how to create component packages and how to declare a component with unique behavior by inheriting an existing component and overriding some of its methods. You also learned how to apply role-based security to component methods to prevent unauthorized access. You’ve probably already heard a lot of talk about how ColdFusion components are similar to objects in object-oriented programming languages, but although some similarities do exist, the two are very different. In short, don’t try too hard to make ColdFusion components act the same as objects, and don’t labor for hours on end creating elaborate coding schemes so that your components are forced into a bad ballet where they must dance and act like real objects in Java or C++, because you’re only going to end up spending a lot of time being sorely disappointed. Components are not objects; they’re not even surrogates. They’re object wannabes. So don’t be afraid to break certain “object rules,” because they’re not component rules. The only components rules are the ones that you define for your applications. If you decide to directly set or get a persistent component property rather than call a component function to do the same thing, the worst that you get are a few whiny tongue lashings from overly excitable discussion-list members. This article covers only what you need to understand the basics of components. If we start weighing you down with more details before you build some for yourself, we may lose you. Next should you build a couple components; then you finish up with the details that we purposefully omit from this article, including component documentation, metadata, and the many caveats that you encounter in implementing component-based applications. After you finish reading you should have a solid understanding of both the theory and practice of designing and implementing components, and you should understand how critical engineering decisions affect the overall strength of your application.

legal disclaimer

Our website is not responsible for the information contained by this article. Web-articles is a free articles resource.
Suggestion: If you need fresh, daily updated content for your website, feel free to use our service. Click here for more information.

related articles

1. Building the company edit action template
The code in CompanyEditAction.cfm is like the code in CompanyAddAction.cfm, but the edit action updates rather than inserts. Create a file named CompanyEditAction.cfm inside the Ch02 directory, type the code into the file’s editing window, and save the file. <cfquery name=”UpdateCompany” datasource=”#Request.MainDSN#”> UPDATE Company SET CompanyName = ‘#Trim(Form.CompanyName)#’, Address = ‘#Trim(Form.Address)#’, City = ‘#Trim(Form.City)...

2. Adding a New Employee to the Database
The CFQUERY in CompanyDeleteAction.cfm uses a DELETE statement with two SQL clauses: DELETE and WHERE. DELETE tells the database the table from which to delete a record, and WHERE tells the database which record to delete. You can watch the company delete process in action. Point your Web browser to http://<yourserver>/CFMXBible/Ch02/CompanyGetDeleteForm.cfm and enter a CompanyID. (To get a valid ID, go to the company list and pick a number from the ID column.) Click Submit to see the chosen company’s informatio...

3. Modifying an Employee in the Database
The DateFormat() function around the DateOfBirth column in the codereturns the employee’s birth date reformatted according to a display mask. DateOfBirth normally comes back from the database in the following format: 2002-01-01 00:00:00.0 That format is not very user-friendly. Calling DateFormat() with a mask of “mm/dd/yyyy” returns the date as follows: 01/01/2002 This version is, of course, more natural and easy to read. The same is true for the employee edit process...

4. Removing an Employee From the Database
The user must have the capability to remove employees from the database. The employee delete process is a simple combination of techniques that you have already learned, such as retrieving a record from the database, displaying that record in a template, and so on. The first page in this process is nearly identical to the employee get edit form. Create a file named EmployeeGetDeleteForm.cfm inside the Ch02 directory, type the code into the file’s editing window, and save the file. <html> <head> <ti...

5. Making direct links to the forms
Say that you want to modify or delete a company. Right now, you need to remember the company’s ID, go back to the launch pad, click Company Edit, and enter the company ID, all just to get to the edit form. Wouldn’t you rather click a company in the list and go directly to the edit form? ... <table> <tr> <td><b>ID</b></td> <td><b>Name</b></td> <td><b>Address</b></td> <td><b>City</b></t...

6. Using a Custom Tag
Custom tags are reusable, developer-authored extensions to the ColdFusion language. The custom tag that you create in the following parts displays today’s date in a familiar format. Create a file named TodaysDate.cfm inside the Ch02 directory, type the code into the file’s editing window, and save the file. <cfoutput>#DateFormat(Now(), “ddd, mmm d, yyyy”)#</cfoutput> Now() returns the current date and time, and DateFormat() reformats the date. To call your custom tag, open index.cfm, a...

7. Creating your physical data model
Physical data models are extracted from their logical counterparts by mapping logical objects to physical objects supported by the target database platform. The following table shows the relationship between logical and physical objects. In many cases, your physical data model almost mirrors your logical data model because entities typically map directly to the tables that store them. Exceptions to this rule are logical data models that contain nonspecific relationships and entity subtypes. Although entity subtypes are an advanced top...

8. Understanding All Relational Result Sets
This article can help you better understand complicated SQL containing multitable joins, group-related clauses, and aggregate functions—by far the most problematic topics for most database developers. You also learn the correct way to handle database exceptions and incorporate them as actual functionality in your ColdFusion application. You learn, too, how to increase performance by caching queries in memory for fast access. You can memorize SQL clauses and Bachus-Naur forms until you’re blue in the face, ...

9. How and when to use Group by Having and Distinct
After learning how SQL works internally, you can better learn how to put the more complicated aspects of it to use. First we need to clarify the difference between GROUP BY and DISTINCT. Quite a bit of confusion exists over these two clauses, because they often produce the same query results but for very different reasons. In fact, GROUP BY and DISTINCT are not related in any way whatsoever. The GROUP BY clause produces as its intermediate work product a table of rows representing each group, and a sort of “invisible third dimen...