Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practices for static constructors

Tags:

I want to create an instance of a class and call a method on that instance, in a single line of code.

PHP won't allow calling a method on a regular constructor:

new Foo()->set_sth(); // Outputs an error. 

So I'm using, if I can call it that, a static constructor:

Foo::construct()->set_sth(); 

Here's my question:

Is using static constructors like that considered a good practice and if yes, how would you recommend naming the methods for these static constructors?

I've been hesitating over the following options:

Foo::construct(); Foo::create(); Foo::factory() Foo::Foo(); constructor::Foo(); 
like image 867
Emanuil Rusev Avatar asked Mar 20 '11 11:03

Emanuil Rusev


People also ask

When would you use a static constructor?

A static constructor is used to initialize any static data, or to perform a particular action that needs to be performed only once. It is called automatically before the first instance is created or any static members are referenced.

Should a constructor be static?

Java constructor can not be static One of the important property of java constructor is that it can not be static. We know static keyword belongs to a class rather than the object of a class. A constructor is called when an object of a class is created, so no use of the static constructor.

Can you have a static constructor?

A class or struct can only have one static constructor. Static constructors cannot be inherited or overloaded. A static constructor cannot be called directly and is only meant to be called by the common language runtime (CLR). It is invoked automatically.

How many times static constructor is executed?

Times of Execution: A static constructor will always execute once in the entire life cycle of a class. But a non-static constructor can execute zero time if no instance of the class is created and n times if the n instances are created.


2 Answers

Static constructors (or "named constructors") are only beneficial to prove an intention, as @koen says.

Since 5.4 though, someting called "dereferencing" appeared, which permits you to inline class instantiation directly with a method call.

(new MyClass($arg1))->doSomething(); // works with newer versions of php 

So, static constructors are only useful if you have multiple ways to instantiate your objects. If you have only one (always the same type of arguments and number of args), there is no need for static constructors.

But if you have multiple ways of instantiations, then static constructors are very useful, as it avoids to pollute your main constructor with useless argument checking, weakening languages constraints.

Example:

<?php  class Duration { private $start; private $end;  // or public depending if you still want to allow direct instantiation private function __construct($startTimeStamp = null, $endTimestamp = null) {    $this->start = $startTimestamp;    $this->end   = $endTimestamp; }  public static function fromDateTime(\DateTime $start, \DateTime $end) {     return new self($start->format('U'), $end->format('U')); }  public static function oneDayStartingToday() {     $day = new self;     $day->start = time();     $day->end = (new \DateTimeImmutable)->modify('+1 day')->format('U');      return $day; }  } 

As you can see in oneDayStartingToday, the static method can access private fields of the instance! Crazy isn't it ? :)

For a better explanation, see http://verraes.net/2014/06/named-constructors-in-php/

like image 149
Florian Klein Avatar answered Oct 29 '22 23:10

Florian Klein


The naming of any method should be with intention revealing names. I can't tell what 'Foo::factory' does. Try to build to a higher level language:

User::with100StartingPoints(); 

This would be the same as:

$user = new User(); $user->setPointsTo(100); 

You could also easily test whether User::with100StartingPoints() is equal to this.

like image 28
koen Avatar answered Oct 29 '22 23:10

koen