Changing the Super Scope in a CFC

I'm starting to get a little bored of my blog, all I seem to be posting is releases and updates for open source stuff that I have written.  So I decided in 2007, I would try and regularly blog all the weird and wacky stuff I just happen to try in my 'test' folder on ColdFusion, and what the results where.  Who knows, we may even learn something along the way.

Today's fun and games came from a weird idea I was having with the Decorator pattern, and I thought to myself: 'I wonder what happens if you set another CFC to the SUPER scope within another CFC'.

It's an interesting idea, I mean, at one end of the spectrum it could possibly allow you to dynamically change inheritance at runtime, which could be interesting, at the other end, it could throw a big fat error.

So I decided to write 3 CFCs: Top, Bottom and Super.

Top.cfc sits at the top of the inheritance hierarchy, and looks like this:

<cfcomponent name="Top">

<cffunction name="dothis" hint="" access="public" returntype="string" output="false">
  <cfreturn "top">
</cffunction>

</cfcomponent>


That 'doThis()' function is going to be our basis for seeing what happens.

Bottom.cfc extends Top.cfc and looks like this:

<cfcomponent name="Bottom" extends="Top">

<cffunction name="SuperDoThis" hint="" access="public" returntype="string" output="false">
   <cfreturn super.doThis()>
</cffunction>

<cffunction name="resetSuper" hint="" access="public" returntype="void" output="false">
    <cfset super = createObject("component", "Super")>
</cffunction>

</cfcomponent>


So now we have 2 ways of calling 'doThis()', be can call bottom.doThis() which will go via the usual inheritance mechanism, and bottom.superDoThis(), which will go via super.doThis()

The method resetSuper() will allow us to place a CFC of type Super in the variables scope under the name super.

Super.cfc simply does this:

<cfcomponent name="Super">

<cffunction name="dothis" hint="" access="public" returntype="string" output="false">
    <cfreturn "super">
</cffunction>

</cfcomponent>


Which allows us to see what happens.

So in out test bed, we have:

<cfscript>
    bottom = createObject("component", "Bottom");
</cfscript>

<cfoutput>
    #bottom.doThis()# : #bottom.superDoThis()#
</cfoutput>


And the output from this is:

top : top

So doThis() returns 'top' and superDoThis() return 'top' as well, which is to be expected, as we haven't done anything to change the inheritance structure.

Now, we add this line to it:

<cfscript>
    bottom.resetSuper();
</cfscript>


Which overwrites super with the Super.cfc , and we run the same test code again, and the results come back with:

top : super

So doThis() returns 'top' but superDoThis() return 'super', meaning that the 'doThis' found in Super.cfc is actually run instead.

This means that ColdFusion must resolve the variable 'super' before it actually looks up the inheritance tree, however, you can't dynamically change the inheritance structure of the CFC at run time, which would have been a cute trick.

So what can you actually do with this? Honestly, I'm not entirely sure, but it's interesting to know that you can.

Leave a Comment

Comments

  • Daniel D. | January 18, 2007

    have you tried setting this.super also? Just like the process for mixins.

    cfset THIS.super = createObject("component", "Bottom");
    cfset VARIABLES.super = THIS.super

  • Mark | January 18, 2007

    Daniel,

    Interesting idea. I gave it a go, but nothing changed.

    If you look at a CFC, there is no super in the ‘this’ scope, so I’m not surprised it had no effect. Cute idea tho’!

  • Andrew Scott | February 6, 2007

    Mark,

    Looking at the code I knew exactly what was to be expected before you described it. The reason behind this is that Coldfusion sees functions as a structure, what this means is that you are replacing the function, in the same way you override the super in the first place, but as this is not seen in the variables it is handy to know that this is possible though.

    As to why you would want to, not sure but I am sure there may be something out there that might benefit from it:-)