init() or __contruct()

I realize in theory they are both one and the same with their functionality but I’m just curious to hear what others think.

The only reference I had where it said to use one over the other was with the Flex development where it said use init so you don’t recall the construct more than once. (since flex you’ll constantly initiate a class over and over - even the same class - same object).

The purpose of my use is just to set a page heading automatically (built for a calendar system, pulls the month and sets it to the title) so that you just put echo $this->title and regardless what month / year you have the proper heading for your calendar.

So should I call it in an init or a __construct?

Thanks for any feedback.

Reading into it, I looked at some of the Zend framework uses and according to it’s setup, init is called by the constructor and generally not by the user (or at least it shouldn’t be). Now while checking out the Yii documentation there is lots of classes that use both and as flexible as it is apparently we can override them all.

So since I’m not using any of the Yii framework classes to inherit, I’ll go about that method to allow overriding of the init function to any potential members who use my class later for an application.

I’m going to do




function __construct() 

{

     init();

}


public function init()

{

      // code in here

}



I’m still open to anyones opinions :)

I dislike the init() thing. The purpose of a constructor is to initialize an object (surprise!), so it is unclear what init() does. Unclear code should be refactored, imo. I feel an especially sharp pain when I see an init() but no constructor. And even worse, when I see something like this:




public function init() {

    ...

    $this->_initialized=true;

}


public function getIsInitialized() {

    return $this->_initialized;

}



This kind of thing is an indication that things have gone wrong.

Anyway, the suggestion to call initialisation methods from a constructor is absolutely normal. But please call it/them something meaningful; init() tells me absolutely nothing about what the method does.

init() is particularly helpful when extended classes would forget to call parent implementation. It may not be the proper approach, but definitely comfortable. :)

If you document what init is for would it really matter then? Like you document that the construct runs on a new instance, and then it calls the initiliazing function which calls all the default values and functions in the class to set.

Because in all theory, the only purpose I’m using the init is to make it public / private / protected sort of gig. The construct actually assigns variables and my init is now calling functions.

So is it a big deal to have it named init? I completely agree with having your functions and variables mean something to what you’re using them for.

Anyway thanks for the input :)

One of the reasons for init() is about life cycles of an object (or a component to be exact).

With an init() method, it is possible to configure an object after it is instantiated while before fully initialized. For example, an application component could be configured using app config. If you override its init() method, you will be sure that the configuration is applied and you can safely to check if everything is ready. Similar thing happens to a widget and other configurable components.

Even if init() is called within constructor rather than by another object, it has meaning. For example, in CApplication, there are preInit() and init(). They set up the life cycles of an application and may be overridden so that the customization only occurs at expected life cycles.

I agree with you that the method naming is very important. Here in Yii, init() method means that an object is already fully configured and some additional initialization work should be done in this method.

So I guess it’s a bad idea to have functions that you would normally call to run an application called within the init in the event someone extends your class?

For example what I made this topic about was my calendar class application. I ended up passing 3 values through the constructor to assign (or assign default values) and then I call the init function which calls 2 or 3 functions to setup the application to be displayed (it builds the calendar, gets the month / year for the title bla bla).

But if someone extends the init function, they essentially overwrite the calls to make the calendar and all that. So should I just be ignoring using the init function and instead put those calls in the constructor - then make an empty init function in order for extensibility?

Every function should exist for a reason. In the Yii case, the init() method is mainly offered to allow customization at certain life cycle of a component. In your calendar application, you may or may not need init(). If you intend to release it for public use, I would suggest you be more conservative at allowing customization. That is, do not define init() unless you have strong reason for it. Once you provide a protected or public method, it means you need to maintain it in future releases.

Well, that’s a bug and your testing will find it ;)

What concerns me is that it becomes the norm. I’ve seen the problems this “approach” can cause. Oddly, I’m about to start a job tidying up a system that is in trouble largely due to init() being used, obviously completely inappropriately. It’s interesting to see that this seems to have come from Zend, because I’ve only seen this behaviour in PHP developments.

Having constructors call initialization methods is routine, but they should still be meaningfully named, imo. I really object to init(), because it says nothing. I have no choice but to wade through code to see what it’s really doing.

So, I guess I’m saying no in answer to your question; documentation isn’t appropriate; the code should be clearer.

Surely, but that gives headaches. :)

In many cases in Yii, like CController, init() is an empty function only waiting to be extended. Since it serves very general purpose, it can hardly be named better. Or, does ‘afterConstruct’ give you more details about its goals?

Then would it not be more appropriate to model the object’s life cycle (with an appropriate pattern of which I know you will be aware)?

Yes, but the way it has been implemented in Yii is that I have to ask the object something conditionally to determine its state; that’s a procedural way of implementing something that oo can do for us. And that means that you have to write the code that supports and answers those questions. That’s added complexity.

Yes, but my point is that you shouldn’t have to check.

Ugh! It doesn’t mean that, you still have to ask the object. And I have to read the code to see what init() does in each case. Double ugh!

I think we’d be better off with more use of well established patterns (namely strategy and state – the behavioural ones); the internal use of behaviors (mixins), since we already have them and they behave a bit like strategy; more consideration of polymorphism (see strategy and state); and either null objects and/or a null behavior.

Hope that provides some food for thought.

Indeed. If you wilfully break things, then they will be broken.

Well, on that basis you could justify an ‘extend<someMethod>’ method being called at the end of every method in a class. Y’know, just in case you need to extend or override something. In fact, you make my case nicely. Why have ‘afterConstruct’? Because everything you do to an object once it’s been instantiated is an ‘afterConstruct’! :P (But this isn’t really the point as Qiang has made clear.)

If you need to do something with an object then do it. No need to hide it in some init(). If you want to extend an object in some way then create a new subclass and in its constructor call the parent constructor and do the stuff you need. Polymorphism will take care of the rest of things.

If a object has states, which implies behavioural change, or has behavioural changes itself, then let the object manage them.

Let me try and explain what I mean. Say you have some recording device. When you switch it on, it initialises itself (constructor). All buttons are off. But, each button (action) now has a set of behaviours assigned to it (by the constructor). If you press Record nothing happens (null). If you press Stop nothing happens (null). But if you press Play, then as well as starting to do something and lighting up the button, the behaviours of the Stop and Record buttons are changed. Now, if I press Record, the machine starts to Record and the Record button lights up. And so on.

The important point is that when Record was pressed, at no time did something have to enquire as to the state of the machine.




if machineState = 'Stop'

    doStopStuff

elseif machineState = 'Record'

    doRecordStuf

...



And yet the results of pressing Record each time were radically different.

I’m sure you understand.

Now, if you are not familiar with behavioural patterns, you are probably thinking: But what about states that Yii doesn’t know about? Well, these patterns cover that; they are fully extensible.

More snacks and nibbles to keep you going…

I don’t quite understand the word “have to ask the object”. Do you mean checking the flag isInitialized? In general, we may need to check this flag in setters only because the setters may be used when the object is configured.

For the life cycle thing, in Yii, most components follow the simple one: construct -> init -> run -> desctruct. If needed, this can be subdivided into smaller cycles by init and run. I can’t think of a better name than init here.

As pestaa said, init() is more like a placeholder which is empty in most cases. So the descendant classes need to document it well to tell what is done in this method. Or better, this method calls some other methods with better names.

I don’t think behaviors are good here to replace init(). Behaviors are too automagical, and they incur performance degradation.

OOP doesn’t mean things have to go in a twisted way. In general, I don’t like most java code, because people craft code that are seemingly aesthetic but are hard or unnaturally to use (they do offer great flexibility for customization, though)

Yes, put everything in the constructor and let folk use the other methods to customize. They can always extend your class, override the constructor, and call parent::__construct(); at the start of it. Job done.

Yes, I mean checking state in a procedural way.

Sure. I think I’ve made it clear that I don’t like this.

In my view, that’s a symptom of the problem. You are trying to model numerous states and give them the same name. The name doesn’t work because it doesn’t tell you anything. This is the heart of my issue.

This has nothing to do with Java or “twisted” use of OO, though. I think that the init() idea is poor. It offers limited flexibility, but offers no feedback on what it is doing. It’s also confusing. And I think it will come back to bite you, which is a shame.

Since we know that Yii objects have state, then we should model that – which simultaneously provides extensible state, and would be very powerful – and not represent it in a procedural way, which ultimately does result in "twisted" OO, imo.

Maybe you could give some concrete suggestions on how to improve these?

I clearly understand your theoretical problem now.

I believe that the current lifecycle looks something more like construct & init -> run -> desctruct, because the first two methods are strongly coupled.

It also means there are no additional states, just more than one method deal with the first state.

Although this design decision can be reviewed and corrected, I think there are other mistakes that deserve more attention than this one.

I knew that was coming :unsure:

I’m just going to grab a class diagram and see how extensive the changes would be.

Could you give me some hints on the main objects with life cycles. Thanks.

To be honest, I still don’t see the problem. Perhaps I am too much into it.

No, construct and init are not tied together. As I already explained, between the two, external configurations may be applied to a constructed (yet not initialized) object.