<CFWTF>

Objects on the fly

Did you know that functions have references in CF? This makes for some interesting mechanics, one of which is the ability to create (almost) objects on the fly without a CFC. Think about it. An object is just a collection of properties and methods, right. So if you could create a function and stick it in a structure key along with other properties, you have an (almost) object. Consider the following:

<cffunction name="newCar">
   <cfargument name="numDoors" type="numeric" required="true">
   <cfargument name="color" type="string" required="true">
   <cfargument name="driverSide" type="string" required="false" default="left">
   <cfset returnValue = structNew()>
   <cfset returnValue.numDoors = Arguments.numDoors>
   <cfset returnValue.color = Arguments.color>
   <cfset returnValue.driverSide = Arguments.driverSide>
   <cfset returnValue.openSunRoof=fnOpenSunRoof>
   <cfreturn returnValue>
</cffunction>

<cffunction name="fnOpenSunRoof">
   <cfreturn "Weee! Fresh air and the potential for bird droppings!">
</cffunction>

<cfset myCoupe = newCar(2,"blue")>

<cfoutput>
#myCoupe.openSunRoof()#<br>
</cfoutput>

Pretty sweet, huh? Cool?...Absolutely? Useful?...You bet it's not! Did I mention cool?

of course, one of the most important aspects of object oriented programming is having separate instance data, and having the methods be aware of which instance they're attached to. Our on-the-fly objects don't do that, and the only way I can think of to make them do it is to actually pass the struct itself in as an additional parameter, which decidedly deflates the cool factor.

<cffunction name="newCar">
   <cfargument name="numDoors" type="numeric" required="true">
   <cfargument name="color" type="string" required="true">
   <cfargument name="driverSide" type="string" required="false" default="left">
   <cfset returnValue = structNew()>
   <cfset returnValue.numDoors = Arguments.numDoors>
   <cfset returnValue.color = Arguments.color>
   <cfset returnValue.driverSide = Arguments.driverSide>
   <cfset returnValue.openSunRoof=fnOpenSunRoof>
   
   <cfset returnValue.trunkIsOpen = false>
   <cfset returnValue.openTrunk = fnOpenTrunk>
   
   <cfreturn returnValue>
</cffunction>

<cffunction name="fnOpenSunRoof">
   <cfreturn "Weee! Fresh air and the potential for bird droppings!">
</cffunction>

<cffunction name="fnOpenTrunk">
   <cfargument name="this">
   <cfset this.trunkIsOpen = true>
</cffunction>

<cfset myCoupe = newCar(2,"blue")>
<cfset mySedan = newCar(4, "charcoal")>

<cfset myCoupe.openTrunk(myCoupe)>

<cfoutput>
#myCoupe.openSunRoof()#<br>

Coupe Trunk Open?: #myCoupe.trunkIsOpen#<br>
Sedan Trunk Open?: #mySedan.trunkIsOpen#<br>
</cfoutput>

That's decidely kludgy, and it still doesn't take care of inheritance, or private/public scopes, or polymorphism, but it still might be at least a little useful...maybe...kindof...in a very strange and improbable set of circumstances that I can't even think of right now...maybe....ah, probably not.

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
BlogCFC was created by Raymond Camden. This blog is running version 5.7.
</CFWTF>