Constructors
Moderator: General Moderators
Constructors
I have a simple question about using constructors in classes. Should I always define a constructor in classes, even when I don't want to set any initial properties of the object upon its creation (in the latter case I could use some kind of 'blank' constructor, that is, set the variables to NULL)? What is your opinion?
Yes, I think you should always have a constructor.
Where possible, I prefer "rich" constructors and more immutable objects; however when that's not possible, a simple no argument constructor that initialiazes all variables to 0, false, NULL, "", array() as approrpriate for the member variable data type is good.
Where possible, I prefer "rich" constructors and more immutable objects; however when that's not possible, a simple no argument constructor that initialiazes all variables to 0, false, NULL, "", array() as approrpriate for the member variable data type is good.
A "rich" constructor is one that takes enough arguments to fully initialize the instantiated object.
I strongly dislike called lots of setters to configure an object. I'd rather have that taken care of by the constructor, etc. In many cases an "Empty Object" doesn't makes a lot of sense to me, so I want my objects always in a "real" state.
Code: Select all
class Foo {
var $bar;
var $baz;
// Default, non-rich constructor
function Foo() {
$this->bar="";
$this->baz=array();
}
// versus
// Rich, constructor
function Foo($bar,$baz=array()) {
if (is_string($bar)) $this->bar=$bar; else $this->bar="";
if (is_array($baz)) $this->baz=$baz; else $this->baz=array();
}
// or
// Alternative type of rich constructor
functrion Foo($bar) {
$this->baz=array();
if (is_string($bar) {
$this->bar=$bar;
$query = "SELECT baz FROM foo WHERE bar='$bar'";
$reg = Registry::instance();
$db = reg->getDB();
$rs = $db->query($query);
while ($row = $rs->next()) {
$this->baz[]=$row['baz'];
}
} else $this->bar="";
}
}I'll still offer accessors/mutators as needed by the class. But I particularly detest the one style of OOP that some people practice:feyd wrote:I prefer having accessors for almost all properties/members except where they are static/constant (object lifetime relative, obviously) in nature.. therefore, my constructors now-a-days rarely have an argument list..
Code: Select all
$foo = new Foo();
$foo->setBar($bar);
$foo->setBaz($baz);
$foo->doSomething();
// why not
$foo = new Foo($bar,$baz);
$foo->doSomething();
// or
$foo = new Foo($bar);
$foo->doSomething($baz);Using setters to replace either Constructor arguments or not remove "real" arguments from methods is only complicating your code. Using setters to mutate an existing object from one valid state to another, is perfectly fine, however.
One of the only arguments for arugmentless constructors is for toolset manipulation, aka JavaBean style approaches. I'm not a big fan of the extreme reliance on reflection, etc, but I can understand where its useful, on occasion.
No problem with me then. I think part of the problem is that tool set writers are typically the best OOP'ers around, but they forget to turn-off the toolset writer hat when explaining OOP to newcomers and newcomers end up writing "normal" code as if it were toolset code.feyd wrote:the project I'm working on is a toolset of sorts.. so yeah.. we rely heavily on reflection among other things for the IDE
Depends on each class actually. I usually only provide a constructor if it's necessary, and I rather use member assignment in the class declaration rather then setting the values explicitly in constructor, for simple values. This goes only for default values, such as '' and null, of course.
For the most cases, I think the only thing that should go into a constructor is something that the class cannot be created without.
Also, there are cases when subclassing is made much easier if you don't declare a constructor in the parent class.
For the most cases, I think the only thing that should go into a constructor is something that the class cannot be created without.
Also, there are cases when subclassing is made much easier if you don't declare a constructor in the parent class.
The point of a constructor is that it allows you to make sure the object goes in a valid state as soon as it's instantiated. If there is no invalid state, there is no constructor needed.
In case there are invalid states, you should provide a constructor that sets the object into a valid state. Assuming that you only use operations of the class (instead of manipulating members directly) this should allow you to always stay in a valid state too.
Offcourse, your constructor can accept parameters, and you can use those to call Setters...
In case there are invalid states, you should provide a constructor that sets the object into a valid state. Assuming that you only use operations of the class (instead of manipulating members directly) this should allow you to always stay in a valid state too.
Offcourse, your constructor can accept parameters, and you can use those to call Setters...
It all depends on the object really.
I tend to do as much as I can in the constructor, as nielsene has said, but that means making some assumptions:
(1) all the necessary parameters are available at the point where the object is instantiated
(2) the state which you are setting in the constructor only needs to be set once
If either isn't true, refactor the code out of the constructor into an interface method.
I tend to do as much as I can in the constructor, as nielsene has said, but that means making some assumptions:
(1) all the necessary parameters are available at the point where the object is instantiated
(2) the state which you are setting in the constructor only needs to be set once
If either isn't true, refactor the code out of the constructor into an interface method.
I guess I would like to add another caveat ... I would caution beginners to OOP from writing classes without constructors. In many cases it leads to simply packaging functions into a class -- the resulting classes could basically be static, especially if they're using the ->setFoo method of "argument passing" to the member functions.
Many patterns and more involved creation methods will move away from a rich constructor, but most of these rely on learning to use data+function packaging into classes first.
In some languages (Java) there can be immense benefits from creating immutable objects (ie classes with no setters or other mutators). Some patterns (Flyweight) also rely on immutable objects. My impression is that the Java arguments for immutability are less in PHP, but at times they are still valid. (Actually, does anyone know of a good PHP-analog to Joshua Block's Effective Java?)
Many patterns and more involved creation methods will move away from a rich constructor, but most of these rely on learning to use data+function packaging into classes first.
In some languages (Java) there can be immense benefits from creating immutable objects (ie classes with no setters or other mutators). Some patterns (Flyweight) also rely on immutable objects. My impression is that the Java arguments for immutability are less in PHP, but at times they are still valid. (Actually, does anyone know of a good PHP-analog to Joshua Block's Effective Java?)