Tuesday, September 06, 2011

Automatically assign constructor parameters to private properties

In Scala, a JVM language, constructor parameters become private fields of the class, by default:
class Person(age:Int) {
  def grow() = {
    age += 1
  }
}
I find it handy, as I always use private properties which are the target of dependency injection, in particular constructor injection.
Here's how to emulate this functionality in PHP, with great hacks. I post this code here so it won't be lost in the interwebs.

7 comments:

Ocramius Aethril said...

The idea is quite nice, but I'd prefer to see that function placed as a static method, thus usable with inheritance and with the new coming threats :D

Marijn said...

As much as I like this if it were a language construct, implementing it like this feels too hackish for me... Than again, I prefer explicit over magic. Perhaps it's just my taste...

Anonymous said...

I doubt that all casual readers will understand why this is necessary in some cases - why it isn't always possible to simply set $this->first in the constructor. It would be helpful to many if you posted a brief explanation - the example you posted could simply set $this->first from the constructor, so it doesn't demonstrate when/why you would need this.

Dominik said...

I also find that a bit too hackish. I mean it saves you a bit of code you'd need to write but I would rather write it than introduce this magic, which might not be clear to everyone reading my code.

Although I always try to not use Reflection as that can get very costly when instanciating a lot of objects that way.

But having that as a language construct would be very cool like it's in Scala :)

Giorgio said...

It's not intended for real world usage, and never *required*.
I had to use reflection because when outsourcing the code from the constructor, private fields become not visible. I would prefer it as a language feature like Marijn and Dominik said.
The only usage for this code is quick experimentation (call it pretotyping): not having to patch the PHP core to see if the feature comes handy or it's horrible.

markus said...

For simple DTO's I use this approach:

class MyDto extends ArrayObject
{

public function __construct($id, $name)
{
parent::__construct(compact('id', 'name'));
}

}

This has some benefits and is simple. But of course the properties are public. Its just a tradeoff...

Giorgio said...

I too use ArrayObject as a low-cost DTO, there's usually no problem with public properties on them.

ShareThis