tags:

views:

800

answers:

3

I've never seen code like this:

public static function getInstance()
{
    if ( ! isset(self::$_instance)) {
        self::$_instance = new self();
    }
    return self::$_instance;
}

Is it the same as new className() ?

EDIT

If the class is inheritant,which class does it point to?

+9  A: 

self points to the class in which it is written.

So, if your getInstance method is in a class name MyClass, the following line :

self::$_instance = new self();

Will do the same as :

self::$_instance = new MyClass();



Edit : a couple more informations, after the comments.

If you have two classes that extend each other, you have two situations :

  • getInstance is defined in the child class
  • getInstance is defined in the parent class

The first situation would look like this (I've removed all non-necessary code, for this example -- you'll have to add it back to get the singleton behavior)* :

class MyParentClass {

}
class MyChildClass extends MyParentClass {
    public static function getInstance() {
        return new self();
    }
}

$a = MyChildClass::getInstance();
var_dump($a);

Here, you'll get :

object(MyChildClass)#1 (0) { } 

Which means self means MyChildClass -- i.e. the class in which it is written.


For the second situation, the code would look like this :

class MyParentClass {
    public static function getInstance() {
        return new self();
    }
}
class MyChildClass extends MyParentClass {

}

$a = MyChildClass::getInstance();
var_dump($a);

And you'd get this kind of output :

object(MyParentClass)#1 (0) { }

Which means self means MyParentClass -- i.e. here too, the class in which it is written.




With PHP < 5.3, that "the class in which it is written" is important -- and can sometimes cause problems.

That's why PHP 5.3 introduces a new usage for the static keyword : it can now be used exactly where we used self in those examples :

class MyParentClass {
    public static function getInstance() {
        return new static();
    }
}
class MyChildClass extends MyParentClass {

}

$a = MyChildClass::getInstance();
var_dump($a);

But, with static instead of self, you'll now get :

object(MyChildClass)#1 (0) { } 

Which means that static sort of points to the class that is used (we used MyChildClass::getInstance()), and not the one in which it is written.

Of course, the behavior of self has not been changed, to not break existing applications -- PHP 5.3 just added a new behavior, recycling the static keyword.


And, speaking about PHP 5.3, you might want to take a look at the Late Static Bindings page of the PHP manual.

Pascal MARTIN
+1, but I think you meant "denotes" rather than "designs"?
Paul Dixon
@Paul : heu... meant "self acts as an alias to", or "self sort of points to" -- the "designer" verb, in french, can be used for that -- I suppose that's one of the situations in which using the same word in english is not a good idea ;-( I'll edit my answer to fix this ;; thanks :-)
Pascal MARTIN
What if there is `baseclass`,`class`,which one does it point to?
@user : I've edited my answer to give a bit more informations about `self` and inheritance ; and I've also included some informations about `static` in PHP 5.3 ;; hope this helps :-)
Pascal MARTIN
Who couldn't +1 this? :)
Pekka
Thanks ;-) *(Well, I suppose at least **I** cannot +1 this -- as it's my own answer, obvisouly ^^ )*
Pascal MARTIN
Also giving a +1.. where can I give my -100 to PHP designers? :/
gnrfan
A: 

Yes, it's like new className() (referring to the class containing that method), probably used in a Singleton pattern where the constructor is private.

kemp
Exactly!constructor is private!
+1  A: 

This seems to be an implementation of the Singleton pattern. The function is called statically and checks whether the static class has the variable $_instance set.

If it isn't, it initializes an instance of itself (new self()) and stores it in $_instance.

If you call className::getInstance() you will get one and the same class instance on every call, which is the point of the singleton pattern.

I've never seen it this done this way, though, and honestly didn't know it was possible. What is $_instance declared as in the class?

Pekka