Cannot Invoke Method On An Object Of Type coldfusion.runtime.VariableScope With Named Arguments
Posted March 12, 2007 at 8:24 AM
I am getting a very strange error when I try to scope a private method within a ColdFusion component. I have this very simple ColdFusion component:
Launch code in new window » Download code as text file »
- <cfcomponent
- output="false">
-
- <cffunction
- name="PrivateMethod"
- access="private"
- returntype="string"
- output="false"
- hint="Returns an updated string.">
-
- <!--- Define arguments. --->
- <cfargument name="Value" type="string" required="true" />
-
- <!--- Return formatted string. --->
- <cfreturn ("<strong>" & ARGUMENTS.Value & "</strong>") />
- </cffunction>
-
-
- <cffunction
- name="CallMethod"
- access="public"
- returntype="void"
- output="false"
- hint="Invokes the private method.">
-
- <cfset VARIABLES.PrivateMethod(
- Value = "Crazy Bananas!"
- ) />
-
- <!--- Return out. --->
- <cfreturn />
- </cffunction>
-
-
- <cffunction
- name="Debug"
- access="public"
- returntype="void"
- output="true"
- hint="Dumps out private variables.">
-
- <cfdump
- var="#VARIABLES#"
- label="VARIABLES Scope Dump"
- />
-
- <cfabort />
- </cffunction>
-
- </cfcomponent>
It does absolutely nothing. It has one private method named "PrivateMethod". It has two public methods; one, Debug(), that dumps out the variables scope, and another, CallMethod(), that invokes the private method in the VARIABLES scope using named arguments.
Now, if I call the Debug() method on this ColdFusion component I get:
| | | | ||
| | ![]() | | ||
| | | |
As you can clearly see, the method PrivateMethod() is clearly within the VARIABLES scope of this component. However, when I try to call CallMethod():
Launch code in new window » Download code as text file »
- <!--- Create CFC instance. --->
- <cfset objTest = CreateObject( "component", "Test" ) />
-
- <!--- Invoke method (which calls private method). --->
- <cfset objTest.CallMethod() />
... I get this ColdFusion error:
Cannot invoke method PrivateMethod on an object of type coldfusion.runtime.VariableScope with named arguments. Use ordered arguments instead.
Now, I have two options to fix it here. I can either take out the names arguments to the PrivateMethod() function:
Launch code in new window » Download code as text file »
- <cfset VARIABLES.PrivateMethod(
- "Crazy Bananas!"
- ) />
... and just use ordered arguments (values are assigned to arguments in the same order in which they were passed). Or, I can simply not use the a method scope when invoking the private method and let ColdFusion search for the appropriate method:
Launch code in new window » Download code as text file »
- <cfset PrivateMethod(
- Value = "Crazy Bananas!"
- ) />
Both of the "solutions" will allow the code to execute fine. But, of course, this should not be the case. There is no reason that I can see that I should not be able to invoke a private method using its scope.
Any one have any ideas? Is this a bug? Am I just not seeing something?
Download Code Snippet ZIP File
Post Comment | Ask Ben | Permalink | Other Searches | Print Page
Reader Comments
Cool. I knew about the variables.methodcall(namedArg="blah") because I tried it a while back. I just settled on taking out the reference to variables though, since I don't think it does anything for the readability of the program in that case (actually degrades it, imo). But I didn't know I could simply have used ordered arguments.
Strange stuff... keep us updated =)
I head what you are saying on readability. My issues it that I like using the THIS scope when referencing public method within the same CFC. I learned to do this after I once had an ARGUMENTS key and a method name conflicting (it kept trying to invoke the argument "Commit" like it was a method (in the THIS scope)).
So anyway, if I use the THIS scope for public method invocation, which to me ups the readability (very clear what I am referring to), I figure I should use the VARIABLES scope for private methods in order to keep things very consistent.
I agree with that - certainly in my mind if you can do this.publicmethod() you should be able to do this.privatemethod(). And adding the fact that you can use it with ordered arguments just strengthens the case.
I had the same problem today invoking a function in the request scope. We typically copy our UDFs into the request scope so we can reference them from within CFCs.
The original code was:
<cfset var convRate = request.getConversionRate(foo = bar)>
The error was:
Cannot invoke method getConversionRate on an object of type coldfusion.runtime.RequestScope with named arguments.
Use ordered arguments instead.
The bizarre workaround was to create a copy of the function as a local variable and then invoke that copy instead. E.g.
<cfset var getConversionRate = request.getConversionRate>
<cfset var convRate = getConversionRate(foo = bar)>
This is pretty lame. Using ordered arguments wasn't an option because I have multiple optional arguments in my function.
@Leon,
Yeah, I am not sure what the problem is with it. It must be some weird wiring issue behind the scenes that makes it very complicated. Cause to me, a scope is a scope is a scope.
@ben
The variables scope of a component is part of the class definition, not an object instance definition. You can use it for class methods, class constants, et al.
The this scope of a component is part of an object instance definition. You can use it for instance methods, instance properties, et al.
The problem is that ColdFusion has confusing syntax. Implicit scope = variables, unless it = url, form, or other. Explicit scope this. Don't even get me started on the super variable, and how it's a class variable, not an object instance variable. [Say what?]
What's more, is that createObject doesn't necessarily create an object instance. [Say what?] It just creates a reference to the class. You can double check this by creating Java objects. You need to call object=Class.init() to actually get an object instance.
You can't call a private method as a class method. You can only call a private method from an instance.
You called variables.privateMethod, which basically treats the call as if it originated from outside the class. Hence, like a class method.
COldFusion wants you to always use this.privateMethod, which treats the call instead as if it originated from inside the class. Hence, an instance method.
Examples are psuedocode-ey.
This is what you did:
component
function privateMethod private
function publicMethod public
variables.privateMethod
Which is the same as this:
x = createObject(component, foo).privateMethod()
You need to do this:
component
function privateMethod private
function publicMethod public
this.privateMethod
@Alex,
I think that some of what you're saying is on the money. However, calling a method on the variables scope is not the same as calling it on the public face of the component instance.
The reason that you cannot use named arguments on calling the variables scope is because ColdFusion simply doesn't allow it. This, however, is something that is changing in CF9.





