Objects and contructors and init(), oh my!

<cf_disclaimer>

 I am NOT an OOP expert, I don’t play one on TV, nor did I stay in a Holiday Inn Express last night. I am fairly new to OOP. Please keep that in mind when reading this, especially if you wish to flame me.

</cf_disclaimer>

The other day at work there was a discussion outside my office about the way some CF developers are handling the creation on objects and how we use the init() method. The way I handle init() comes from the way I initially learned about using objects. Here’s a snippet:

<cfset myObj = createObject(“component”, “user”).init(args) />

What this does is create an object and call the init() method at the same time. However, one caveat is that in you must specify a returntype (which needs to equal the object you are instatiating) for you init() method, and use <cfreturn this /> in the method.

One of my co-workers thinks this is a bad idea. He suggests doing this:

<cfset myObj = createObject(“component”, “user”) />
<cfset myObj.init(args) />

Why? The only thing I could really make sense of is that we are treating init() as a constructor (because CF does not have *real* constructors), and constructors typically do not return anything (at least, to my knowledge, not in Java -- which I think was the OO language being referenced in the discussion). And by having init() return something, you are ‘breaking’ some OO principles.

While I did not take part in the discussion (because I really didn’t think I could bring anything worthwhile in to the discussion), it got me thinking about the issue

I may be wrong (and if so, please correct me), but in Java, when you create or instantiate an object, you get an init-ed object back (the constructor is called automatically). So, while using

<cfset myObj = createObject(“component”,”user”).init(args) />

 may ‘break’ some OO principles, creating and using the object, to me, seems more OO-like (or Java-like) because you get a fully init-ed object when you create it.

For me, at least, it helps me to understand OOP a bit more when I use

<cfset myObj = createObject(“component”,”user”).init(args) />
because if I were creating classes in Java, I would not have to have a second line of code run my constructor (and I know, I would not have to call me constructor at time of creation either, its just easier for me to ‘get it’ doing it this was)

 

Are there any other compelling arguments for or against either of these methods?

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
Steve Bryant's Gravatar I prefer your method. If for no other reason than because it discourages any future developer from adding anything between the two lines (as they could with the other method).

If you intend that init() should be called upon instantiation, every time, then write your code to reflect that.

Your method (which I use as well) ensures that no-one will try to use the component before it is fully intialized and allows all other code in that component to assume that init() has been run.
# Posted By Steve Bryant | 1/13/06 12:13 PM
dave ross's Gravatar constructors in other languages return something... but it's built into the language:

Class myClass = new Class();

The "new" keyword assigns the instance.

In CF we make our own constructors. Any CF developer not using an init() with <cfreturn this/> is violating best practices and would have a very difficult time convincing me why going against them is a good idea. Frameworks like ColdSpring rely on the fact that developers adhere to best practices... if you have a CFC with an init() method that doesn't return itself it would be incompatible with ColdSpring.
# Posted By dave ross | 1/13/06 12:21 PM
Brian Kotek's Gravatar Method chaining the constructor with the createObject call is definitely superior, becuase it occurs as one atomic action. Doing the init() on a separate line actually means the two events (instantiating the object and calling the constructor) are happening separately, which can introduce issues as Steve mentioned. Sean Corfield has talked about this before too.
# Posted By Brian Kotek | 1/13/06 12:46 PM
Joe Rinehart's Gravatar Hey Scott,

I think you're definitely right in this one. A few things:

>I may be wrong (and if so, please correct me),
>but in Java, when you create or instantiate
>an object, you get an init-ed object back

In Java, that's correct. When using Java from CF, you don't get an init'd Java class back. A Java class can have more than one constructor, each with a different set of arguments. Therefore, creating an init'd Java class in CF looks like this:

<cfset myObject = createObject("java", "some.java.class").init(someArg, another Arg) />

Well, it'd really stink to have to use two different ways of constructing objects - especially if you wanted to swap out a CFC for Java or vice versa - so it only makes sense to use the same format for ColdFusion.

However, that requires the init() method to return this. That's not as "un-OO" as a lot of people think, and it no way makes ColdFusion a less Object-Oriented language. In fact, OO languages have had "constructors" returning instances since before Java came around!

Smalltalk (and Objective C) both work in a sorta similar manner (to my understanding of them). Hell, in Smalltalk, you can call a "constructor" with some arguments, and the constructor may decide you want a different object entirely, and return an instance of *that* object instead of itself/"this"!

IMHO, creating the instance and returning it is *more* object oriented than C++-style constructor, because the responsibility for creation of the actual instance to be constructed is delegated to the class!
# Posted By Joe Rinehart | 1/13/06 1:08 PM
Adam Ness's Gravatar I tend to actually prefer:

<cfinvoke component="FooObject" method="init" returnVariable="fooObjectInstance" argument1="fooarg" argument2="barArg">

because it gives me the benefits of OO, feels more "ColdFusion" rather than Java and works even if security-conscious admins have disabled "createObject" on CFMX 6 servers.
# Posted By Adam Ness | 1/13/06 7:35 PM
Jared Rypka-Hauer's Gravatar I'm with you, Scott... since constructors aren't a language feature in CF, createObject().init() is a convention using a standard name for a method on any object, it bears no comparison to constructors in other languages anyway. Java sets RULES about how you write constructors and CF sets no rules at all about much of anything. Maybe that's why I like it so much.

But seriously, comparing constructors to init() is really like comparing doors on a station wagon to doors on a Jeep. Jeeps are bouncy and fun, but they HAVE NO DOORS unless you choose to mount some... and they can be canvas or plastic or metal. Soft sided? Soft-top? Hard-Top? THAT'S NOT A DOOR, IT'S MADE OF CANVAS!!

Right... whatever.

Laterz (and hoping that last part made sense. hehe.)
# Posted By Jared Rypka-Hauer | 1/14/06 3:54 PM
Sean Corfield's Gravatar application.obj = createObject("component","thing");
application.obj.init(args);

That is not thread-safe. It creates an uninitialized application.obj that cannot safely be used by other threads.

application.obj = createObject("component","thing").init(args);

That, on the other hand, *is* thread-safe - application.obj only exists as a fully-formed, fully-initialized instance.
# Posted By Sean Corfield | 1/19/06 8:41 PM
# Posted By Dan | 9/27/07 11:00 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.9. original design by tri-star web design