ColdFusion, WordPress, Flash & other web things


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.

Comments are closed.