Issues with calling super methods
I ran into serious problems today when I tried to call a super method from an extended CFC. I needed to override the init() method of the parent component but I still needed to call the original method with the whole set of passed arguments. Because the original init() method had a large number of arguments, I wanted to pass them as a collection:
super.init( argumentsCollection=arguments );
However this threw the following error:
Cannot invoke method init on an object of type coldfusion.runtime.Struct with named arguments. Use ordered arguments instead.
I did a bit of research and found this thread on CFCDev mailing list archive. After reading through the thread and experimenting with the suggested solutions, this is what I found out:
Using CFINVOKE
Sean Corfield says that this is a known issue in MX 6.1 and Ben Curtis recommends using the cfinvoke tag instead and loop over the arguments structure to pass each argument to the super method:
<cfinvoke component="super" method="init" returnvariable="ret"> <cfloop collection="#arguments#" item="key"> <cfinvokeargument name="#key#" value="#arguments[key]#"/> </cfloop> </cfinvoke>
But this was the result:
Could not find the ColdFusion Component super.
I tried several syntax combinations to get to the super.init() method but nothing worked.
Some pageContext trickery
Next, I tried this suggested method:
<cfset var context = getPageContext() /> <cfset context.setVariableScope( context.getSuperScope() ) /> <cfinvoke method="super.init" argumentcollection="#arguments#" /> <cfset context.setVariableScope( variables ) />
This is what I got back:
Variable THIS is undefined
The error referred to my parent init() method that returns a reference to the component. At least, the call to super.init() worked and the arguments had been passed (I checked by cfdumping them in the parent init() method).
Hacks = more pain
Apparently, because of the pageContext trickery, you need to scope all public variables thus:
variables.this.var
My experiment finally worked when I switched my return statement to:
<cfreturn variables.this />
Victory!
Consequently, this also means that you need to scope all calls to component methods within the parent if there is a possibility that they will be called from a child. The only variables that can stay unscoped are var-declared local variables.
