# Traits and static methods

- Thread: https://externals.io/message/50258
- Original archive: https://news-web.php.net/php.internals/50258
- Started by Simas Toleikis on 2010-11-16T17:46:09+00:00
- Messages: 11
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #50258 — Simas Toleikis — 2010-11-16T17:46:09+00:00

URL: https://externals.io/message/50258#50258

Hello,

I was just skimming through Traits RFC document on the wiki trying to find a
practical use for them. The first thing that comes to my mind is a Singleton
implementation - this is where I found myself literally "copying" most of
the code in the past. As far as I know there is no way to implement this
pattern properly in PHP without duplicate code (due to lack of multiple
inheritance/templating).

Unfortunately, the same RFC document mentions this for trait methods:

The static modifier is not supported, because it would change the methods
> semantics and references to $this would break.
>

.. and that pretty much defeats Singleton-Trait implementation. Is there any
particular technical/design reasons why traits can't handle $this inside
static methods just like regular static methods do (with a fatal error)?

p.s. a Singleton-Trait implementation could look like:

trait Singleton {
  public static function getInstance() { ... }
}

class Child extends Parent {
  use Singleton;
}

Child::getInstance();

---

## #50267 — Stefan Marr — 2010-11-16T20:21:14+00:00

URL: https://externals.io/message/50258#50267 · In reply to: #50258

Hi Simas:



> The first thing that comes to my mind is a Singleton
> implementation - this is where I found myself literally "copying" most of
> the code in the past. As far as I know there is no way to implement this
> pattern properly in PHP without duplicate code (due to lack of multiple
> inheritance/templating).
> 
> Unfortunately, the same RFC document mentions this for trait methods:
> 
> The static modifier is not supported, because it would change the methods
> > […]
> 
> .. and that pretty much defeats Singleton-Trait implementation. Is there any
> particular technical/design reasons why traits can't handle $this inside
> static methods just like regular static methods do (with a fatal error)?
Hm, good question. I don't recall any implementation details. Haven't touched the code for too long.
From the top of my head, I don't see why it should not work.

If I would have elaborated a bit more what I was thinking when I wrote that comment...

Following the motto 'it is just compiler assisted copy and paste' I think it should be implemented.

Best regards
Stefan


-- 
Stefan Marr
Software Languages Lab
Vrije Universiteit Brussel
Pleinlaan 2 / B-1050 Brussels / Belgium
http://soft.vub.ac.be/~smarr
Phone: +32 2 629 2974
Fax:   +32 2 629 3525

---

## #50268 — Ferenc Kovacs — 2010-11-16T20:55:52+00:00

URL: https://externals.io/message/50258#50268 · In reply to: #50258

> Hello,
>
> I was just skimming through Traits RFC document on the wiki trying to find
> a
> practical use for them. The first thing that comes to my mind is a
> Singleton
> implementation - this is where I found myself literally "copying" most of
> the code in the past. As far as I know there is no way to implement this
> pattern properly in PHP without duplicate code (due to lack of multiple
> inheritance/templating).
>
> Unfortunately, the same RFC document mentions this for trait methods:
>
> The static modifier is not supported, because it would change the methods
> > […]
>
> .. and that pretty much defeats Singleton-Trait implementation. Is there
> any
> particular technical/design reasons why traits can't handle $this inside
> static methods just like regular static methods do (with a fatal error)?
>
> p.s. a Singleton-Trait implementation could look like:
>
> trait Singleton {
>  public static function getInstance() { ... }
> }
>
> class Child extends Parent {
>  use Singleton;
> }
>
> Child::getInstance();
>

for reusable singleton pattern with php 5.3
http://www.slideshare.net/fabpot/design-patternrevisitedphp53
slide 11 and 12

Tyrael

---

## #50269 — Tom Sartain — 2010-11-16T21:22:09+00:00

URL: https://externals.io/message/50258#50269 · In reply to: #50268

>
> for reusable singleton pattern with php 5.3
> http://www.slideshare.net/fabpot/design-patternrevisitedphp53
> slide 11 and 12
>
> Tyrael
>

The problem with the solution presented in the slides is that it
limits every singleton class to only ever be able to inherit from
Singleton, so we can't have a child class that is a singleton while
the parent is not. Something that having Traits would solve. Though
we'd still have singletons, which is a different problem.

-Tom

---

## #50285 — Simas Toleikis — 2010-11-17T06:32:42+00:00

URL: https://externals.io/message/50258#50285 · In reply to: #50267

Hi Stefan,

 Following the motto 'it is just compiler assisted copy and paste' I think
> it should be implemented.
>

Alright then, I am sure someone will find more uses for static methods in
Traits like factories/utilities (especially if traits can be made to work
with late static binding).

I assume this will be implemented in one way or another before or after
first 5.4 alphas! :)

/Simas

---

## #50287 — Simas Toleikis — 2010-11-17T06:40:42+00:00

URL: https://externals.io/message/50258#50287 · In reply to: #50268

Hi Ferenc,


for reusable singleton pattern with php 5.3
> http://www.slideshare.net/fabpot/design-patternrevisitedphp53
> slide 11 and 12
>

As Tom already pointed out - there is that lock-down of your parent(s) to
singletons with this type of implementation and there are other shortcomings
when used with SPL, for example:

class Test extends ArrayObject { }

Without creating some sort of intermediate ArrayObjectSingleton class you
can't make Test a singleton (and traits would solve that).

/Simas

---

## #50290 — Stefan Marr — 2010-11-17T07:55:34+00:00

URL: https://externals.io/message/50258#50290 · In reply to: #50285

Hi Simas:


> Alright then, I am sure someone will find more uses for static methods in
> Traits like factories/utilities (especially if traits can be made to work
> with late static binding).
> 
> I assume this will be implemented in one way or another before or after
> first 5.4 alphas! :)
Send me the tests/phpt-files for it, and I will have a lock at it over the weekend.

Best regards
Stefan


-- 
Stefan Marr
Software Languages Lab
Vrije Universiteit Brussel
Pleinlaan 2 / B-1050 Brussels / Belgium
http://soft.vub.ac.be/~smarr
Phone: +32 2 629 2974
Fax:   +32 2 629 3525

---

## #50310 — Stefan Marr — 2010-11-17T23:10:44+00:00

URL: https://externals.io/message/50258#50310 · In reply to: #50290

Hi Simas:

Thanks for sending me the test cases.
I checked them in, and surprise surprise: it actually was already completely implemented. I didn't had to touch any code...
So the missing bit was being more explicit in the RFC.
I added a section and an example based on your Singleton code.

Now I also remember what the reference to the static modifier was about.

You cannot use it to change it for a standard method.
That means, if you have a normal method, you cannot make it static however, you can for instance make a public method private, or add an alias for it. That was what that statement was referring to.

http://wiki.php.net/rfc/horizontalreuse

Hope that helps
Best regards
Stefan



> Hi Simas:
> 
> 
> > […]
> Send me the tests/phpt-files for it, and I will have a lock at it over the weekend.
> 
> Best regards
> Stefan
> 
> 
> -- 
> Stefan Marr
> Software Languages Lab
> Vrije Universiteit Brussel
> Pleinlaan 2 / B-1050 Brussels / Belgium
> http://soft.vub.ac.be/~smarr
> Phone: +32 2 629 2974
> Fax:   +32 2 629 3525
> 
> 
> --
> 
> 
> 

-- 
Stefan Marr
Software Languages Lab
Vrije Universiteit Brussel
Pleinlaan 2 / B-1050 Brussels / Belgium
http://soft.vub.ac.be/~smarr
Phone: +32 2 629 2974
Fax:   +32 2 629 3525

---

## #50409 — Sebastian Bergmann — 2010-11-22T11:52:10+00:00

URL: https://externals.io/message/50258#50409 · In reply to: #50258

Am 16.11.2010 18:46, schrieb Simas Toleikis:
> p.s. a Singleton-Trait implementation could look like:
> 
> trait Singleton {
>   public static function getInstance() { ... }
> }
> 
> class Child extends Parent {
>   use Singleton;
> }
> 
> Child::getInstance();

 This is not really a good example as the getInstance() method alone is
 not sufficient for a reusable implementation of the Singleton pattern.

 A trait for a reusable implementation of the Singleton pattern should
 look more like

     trait Singleton
     {
         private static $uniqueInstance = NULL;

         protected function __construct() {}
         private final function __clone() {}

         public static function getInstance()
         {
             if (self::$uniqueInstance === NULL) {
                 self::$uniqueInstance = new Singleton;
             }

             return self::$uniqueInstance;
         }
     }

 which of course does not work as traits are stateless and

     class MySingleton
     {
         use Singleton;
     }

     MySingleton::getInstance();

 results in

     Access to undeclared static property: MySingleton::$uniqueInstance

 And rightfully so. Nobody should need a mechanism to make it as easy as
 pie to clutter the code base with singletons ;-)

-- 
Sebastian Bergmann                    Co-Founder and Principal Consultant
http://sebastian-bergmann.de/                           http://thePHP.cc/

---

## #50410 — Simas Toleikis — 2010-11-22T12:47:18+00:00

URL: https://externals.io/message/50258#50410 · In reply to: #50409

Hi Sebastian,

 This is not really a good example as the getInstance() method alone is
>  not sufficient for a reusable implementation of the Singleton pattern.
>

Yes, it was just a pseudo-code and not a true singleton implementation.



>  A trait for a reusable implementation of the Singleton pattern should
>  look more like
> ...
>  which of course does not work as traits are stateless and
>

Would it work if instance is saved inside a local static var like:

public static function getInstance() {

  static $instance = NULL;

  if (is_null($instance)) {
    $instance = new self();
  }

  return $instance;
}

/Simas

---

## #50411 — Stefan Marr — 2010-11-22T12:52:36+00:00

URL: https://externals.io/message/50258#50411 · In reply to: #50410

Hi Simas:


> Would it work if instance is saved inside a local static var like:
> 
> public static function getInstance() {
> 
>  static $instance = NULL;
> 
>  if (is_null($instance)) {
>    $instance = new self();
>  }
> 
>  return $instance;
> }
http://svn.php.net/viewvc/php/php-src/trunk/Zend/tests/traits/language013.phpt?revision=300283&view=markup

The test case says it works ;)

Best regards
Stefan



-- 
Stefan Marr
Software Languages Lab
Vrije Universiteit Brussel
Pleinlaan 2 / B-1050 Brussels / Belgium
http://soft.vub.ac.be/~smarr
Phone: +32 2 629 2974
Fax:   +32 2 629 3525
