Search code examples
functioninheritancecoldfusionencapsulationcfml

Public-private function access via component inheritance in ColdFusion


I am experiencing an unexpected issue with ColdFusion Markup Language. Let's say I have the following components. If both a public and a private function are defined in a "base" component, can the former still invoke the private one when called from an extending "sub" type's instances?

Program.cfc

<cfcomponent>

    <cffunction access="public" name="doOperation"> 
        <cfset this.checkValue(-14)>
    </cffunction> 


    <cffunction access="private" name="checkValue">
        <cfargument name="notNeg" required="yes" type="numeric">

        <cfif arguments.notNeg LT 0 >
            <cfthrow message="Negative Numbers not allowed"> 
        </cfif>
    </cffunction> 

 </cfcomponent>

SubProgram.cfc

<cfcomponent extends="Program">

</cfcomponent>

Run.cfm

 <cfobject component="SubProgram" name="this.instance">

 <cfset this.instance.doOperation()>                      <<<<----ERROR---->>>>

ColdFusion throws the error

method checkValue was not found in component SubProgram. Ensure that the method is defined...

What is the issue here? No brownie points for encapsulation!


Solution

  • The issue is that you're trying to call the checkValue() method as a public method. this does not work in CFML the same way as it does in other languages (a very poor design decision on the part of Macromedia): this is an external reference to the object itself, so if you call this.someMethod(), that's trying to call a public method called someMethod() (as if you were calling myObject.someMethod()). In CFML parlance, the variables scope is the reference to private data/members.

    What you want to do is this:

    <cffunction access="public" name="doOperation"> 
        <cfset variables.checkValue(-14)>
    </cffunction> 
    

    Or simply:

    <cffunction access="public" name="doOperation"> 
        <cfset checkValue(-14)>
    </cffunction> 
    

    Also, if you're using a recent version of CF (eg: CF10 or CF11) you really want to not write your components in tags. It makes for pretty awful-looking code. Try to limit tag usage to view files. CF10 still doesn't have 100% support for all CFML constructs in script, but CF11 does.