Constructors

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
Ree
Forum Regular
Posts: 592
Joined: Fri Jun 10, 2005 1:43 am
Location: LT

Constructors

Post by Ree »

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?
User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Post by nielsene »

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.
Ree
Forum Regular
Posts: 592
Joined: Fri Jun 10, 2005 1:43 am
Location: LT

Post by Ree »

What is a 'rich' constructor?
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

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..
User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Post by nielsene »

A "rich" constructor is one that takes enough arguments to fully initialize the instantiated object.

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 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.
User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Post by nielsene »

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..
I'll still offer accessors/mutators as needed by the class. But I particularly detest the one style of OOP that some people practice:

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);
There are some OOP advocate who say that no method should take any arguments except for setters. I have no idea why they've embraced that idea, but I'll crusade against it. All they've done is exchange one arugment passing convention for another, much more verbose, one.

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.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

the project I'm working on is a toolset of sorts.. so yeah.. we rely heavily on reflection among other things for the IDE
User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Post by nielsene »

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
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.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

heh, yeah I can see that happening pretty easily. :)
User avatar
dbevfat
Forum Contributor
Posts: 126
Joined: Tue Jun 28, 2005 2:47 pm
Location: Ljubljana, Slovenia

Post by dbevfat »

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.
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Post by timvw »

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...
Ree
Forum Regular
Posts: 592
Joined: Fri Jun 10, 2005 1:43 am
Location: LT

Post by Ree »

Thanks for your replies, useful. ;)
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

Post by McGruff »

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.
User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Post by nielsene »

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?)
Post Reply