call of init method in component

273 views
Skip to first unread message

Siegfried Wagner

unread,
Mar 27, 2015, 6:20:58 AM3/27/15
to lu...@googlegroups.com
Hi,

I looked through existing discussions if I could find something to clarify my question about how the init method in components is called with Lucee but couldn't find much.
Btw. I think there are a lot of discussions here not focusing on specific topics but containing a total mixture of everything that comes to mind (especially in threads about the "future of Lucee" ;-))

My questions: how are init methods of components called with Lucee? With creation of the object?
How do you pass a parameter or pass a return value that is not the object (=this)?

I'm a little bit confused because during my research on the topic, I saw so many different interpretations of how the init method is called and the parameters are processed through different ACF versions and where it is called implicitly on creation and where not.

Thanks a lot for clarifying!
Siegfried

Dominic Watson

unread,
Mar 27, 2015, 7:12:29 AM3/27/15
to lu...@googlegroups.com
Hi Siegried,

The init() method will be implicitly called when using the 'new' syntax for creating instances:

var myObjInstance = new myObj();

If you use CreateObject( 'myObj' ), the init() method is *not* called and will need to be called manually, e.g.

var myObjInstance = CreateObject( 'myObj' ).init();

I would say that you should always return 'this' in the init() method, not doing so will cause confusion at best and problems at worst. Though I'd be curious to know what the reason for not returning 'this' is?

Dominic

--
You received this message because you are subscribed to the Google Groups "Lucee" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+un...@googlegroups.com.
To post to this group, send email to lu...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/d1b01e3a-13c9-4fd5-83bb-347f72a42fe1%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Pixl8 Interactive, 3 Tun Yard, Peardon Street, London
SW8 3HT, United Kingdom

T: +44 [0] 845 260 0726 W: www.pixl8.co.uk E: in...@pixl8.co.uk

Follow us on: Facebook Twitter LinkedIn
CONFIDENTIAL AND PRIVILEGED - This e-mail and any attachment is intended solely for the addressee, is strictly confidential and may also be subject to legal, professional or other privilege or may be protected by work product immunity or other legal rules. If you are not the addressee please do not read, print, re-transmit, store or act in reliance on it or any attachments. Instead, please email it back to the sender and then immediately permanently delete it. Pixl8 Interactive Ltd Registered in England. Registered number: 04336501. Registered office: 8 Spur Road, Cosham, Portsmouth, Hampshire, PO6 3EB

Adam Cameron

unread,
Mar 27, 2015, 7:23:50 AM3/27/15
to lu...@googlegroups.com


On Friday, 27 March 2015 11:12:29 UTC, Dominic Watson wrote:
I would say that you should always return 'this' in the init() method, not doing so will cause confusion at best and problems at worst. Though I'd be curious to know what the reason for not returning 'this' is?


Note: at least on ColdFusion, it does not matter what you return from init(), when it's called implicitly (ie: via the new operator). The object itself is always returned by new

I cannot vouch for Lucee in this regard. It's easy enough to test though.

That said, this is not to contradict what Dom says. In fact if anything it concretes his position that one should always return this, so that explicit calls to init() behave the same way as the implicit ones.

-- 
Adam

Walter Seethaler

unread,
Mar 27, 2015, 7:30:46 AM3/27/15
to lu...@googlegroups.com
Depends on how you create your instances - new Foo(), createObject("componen", "Foo).init(), <cfobject...> and <cfinvoke...> have different behaviour. Which way do you use?

I would recommend new Foo(), because it best suits OO programming.

component{


    variables
.blah = "test";


   
function init(required numeric bar, array baz){
        variables
.bar = bar;
        variables
.bazlen = baz.len();  
       
return THIS;  //required in Lucee - while ACF returns this if nothing else is returned
   
}


    array
function something(){}


}

The init method acts as constructor, everything outside of the functions acts as pseudo-constructor (variables.blah="test").

new Foo( 1, [a,b,c] )

Creates the instance calls the pseudo-constructor and the constructor and returns the instance.

createObject("component").init( 1, [a,b,c] );

Creates the instance calls the pseudo-constructor and the constructor and returns the instance.

createObject("component");

Creates the instance calls the pseudo-constructor and returns the instance.


Read the docs for cfobject and cfinvoke. These tags are old, I wouldn't use them anymore.

component{

    array
function init(required numeric bar, array baz){
       
return baz;
   
}

}

As the constructors in Lucee/ACF are no real constructors, but (almost) normal methods, you can return what you want.
I think you shouldn't use this - new Foo() should always return the instance.

component{

   
package function init(required numeric bar, array baz){
       
return this;
   
}

}

new other.package.Foo()

ACF: Throws an exception with the message: Can not access a package method from outside...
Lucee (Bug): Creates the instance, calls the pseudo-constructor and returns the instance.

component extends="Bar" {


}

The Bar.init() method is inherited and called as described above.
If you implement the init-Method in Foo you have to call super.init() manually.


In my opinion, the constructor behaviour is pretty obscure in CF. The main reason is that CF was not designed as an OO language. I hope we can fix this in the future.

Adam Cameron

unread,
Mar 27, 2015, 7:57:52 AM3/27/15
to lu...@googlegroups.com


On Friday, 27 March 2015 11:30:46 UTC, Walter Seethaler wrote:
Depends on how you create your instances - new Foo(), createObject("componen", "Foo).init(), <cfobject...> and <cfinvoke...> have different behaviour. Which way do you use?


That's kinda comparing apples to oranges to pears.

In your comparsion between createObject() and <cfobject>, with createObject() you're chaining a call to init(). If one was to remove the explicit call to init(), do createObject() and <cfobject> differ?

And <cfinvoke> isn't designed for creating objects, it's designed for executing methods. So not a valid comparison I think. That said, if you call init() with <cfinvoke>, does it behave any different to createObject().init() ?


> The main reason is that CF was not designed as an OO language.

Well the bits of CFML you're discussing here were designed to be OO. The problem is that the design was a bit rubbish.

-- 
Adam

Walter Seethaler

unread,
Mar 27, 2015, 8:38:28 AM3/27/15
to lu...@googlegroups.com
On Friday, 27 March 2015 11:30:46 UTC, Walter Seethaler wrote:
Depends on how you create your instances - new Foo(), createObject("componen", "Foo).init(), <cfobject...> and <cfinvoke...> have different behaviour. Which way do you use?


That's kinda comparing apples to oranges to pears.

In your comparsion between createObject() and <cfobject>, with createObject() you're chaining a call to init(). If one was to remove the explicit call to init(), do createObject() and <cfobject> differ?

And <cfinvoke> isn't designed for creating objects, it's designed for executing methods. So not a valid comparison I think. That said, if you call init() with <cfinvoke>, does it behave any different to createObject().init() ?

Sry Adam, I haven't used cfobject or cfinvoke for years and almost forgotten how they work. So I just wanted to provide a link to the docs for Siegfried and compare new with createObject. But you are obviously right with cfobject. Cfinvoke probably behaves like createObject, but you should use it with the returnVariable attribute or you end up creating new instances on every method call. 
 

> The main reason is that CF was not designed as an OO language.

Well the bits of CFML you're discussing here were designed to be OO. The problem is that the design was a bit rubbish.

Well, it depends how you define "was designed". Since CF9 added the new operator, the init method became a kind of constructor (calls the method and returns the instance if nothing else is returned). But the only thing that was designed here is the new operator, but not the language.

Siegfried Wagner

unread,
Mar 27, 2015, 10:51:46 AM3/27/15
to lu...@googlegroups.com
Hi,

thanks for the many replies so far.

I like the answer of Walter Seethaler very much because you show and explain the differences very well. But also the others pointed out one very important aspect I thought it would be different:
you say calling createObject() without expicitly calling init() does not call the constructor (init)? I thought it's always called implicitly in all of todays ColdFusion servers including Railo and Lucee?

But it probably makes the most sense because if I see it correctly using the tag variant with <cfobject> is identical to createObject, and that was also part of my question, how one would provide parameters for the implicit init with the tag call.

Of course, I understand using "new" is the solution to be preferred always. Just wanted to learn to know all the other behaviours as well.

Concerning the return value of the init I guess returning something different than the object itself made sense from the time where init() had to be always called explicitly (e.g. with createObject or <cfobject> and <cfinvoke ...>).
With an implicit call of course it doesn't make sense.

I new tested with Railo 4.1.2 and Lucee 4.5.1 and indeed, it's possible to do nonsense like the following:
<cfset var test = new cfc.test("foo")>

where component cfc.test has:
<cffunction name="init" access="public" returntype="string" output="no">
<cfargument name="text" type="string" required="no" default="">
<cfset var localVar = arguments.text>
<cfreturn localVar>
</cffunction>

and so the resulting content of var test is the string "foo" instead of the object from "new cfc.test()".

Andrew Dixon

unread,
Mar 27, 2015, 11:05:54 AM3/27/15
to lu...@googlegroups.com
Just one thing to add, it is considered best practice now to write your CFC's in script so the example you gave would become something like:

component  {
function init(string text) {
var localVar = arguments.text;
return localVar;
}
}

No <cfscript> tags required.

Kind regards,

Andrew
about.me
mso - Lucee - Member

--
You received this message because you are subscribed to the Google Groups "Lucee" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+un...@googlegroups.com.
To post to this group, send email to lu...@googlegroups.com.

Michael Offner

unread,
Mar 27, 2015, 1:47:06 PM3/27/15
to lucee
that is actually not true, sorry.
When you have a component like this
component {
function init(){
return "susi";
}
}

and a template with this
writedump(new Test());

you get the output "susi" and not the component in Lucee and ACF (10,11) .
In earlier version (Railo back then) was returning always the instance, but for compatibility we changed this behaviour.
When thinking about it i have no clue why we did, because it is really stupid.

Micha








--
You received this message because you are subscribed to the Google Groups "Lucee" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+un...@googlegroups.com.
To post to this group, send email to lu...@googlegroups.com.

Michael Offner

unread,
Mar 27, 2015, 1:50:31 PM3/27/15
to lucee
@Walter

could you raise a ticket about the following? Thanks in advance.
ACF: Throws an exception with the message: Can not access a package method from outside...
Lucee (Bug): Creates the instance, calls the pseudo-constructor and returns the instance.

Micha 

--
You received this message because you are subscribed to the Google Groups "Lucee" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+un...@googlegroups.com.
To post to this group, send email to lu...@googlegroups.com.

Michael Offner

unread,
Mar 27, 2015, 1:53:36 PM3/27/15
to lucee
@Walter

could you raise a ticket about the following? Thanks in advance.
ACF: Throws an exception with the message: Can not access a package method from outside...
Lucee (Bug): Creates the instance, calls the pseudo-constructor and returns the instance.

Micha 

On Fri, Mar 27, 2015 at 12:30 PM, Walter Seethaler <seet...@nbsp.com> wrote:

--
You received this message because you are subscribed to the Google Groups "Lucee" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+un...@googlegroups.com.
To post to this group, send email to lu...@googlegroups.com.

Walter Seethaler

unread,
Mar 27, 2015, 4:10:49 PM3/27/15
to lu...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages