note 52003 added to language.oop5.patterns

From: Date: Mon, 18 Apr 2005 15:06:22 +0000
Subject: note 52003 added to language.oop5.patterns
Groups: php.notes 
Request: Send a blank email to php-notes+get-88168@lists.php.net to get a copy of this message
In response to Scott Mattocks response to Jimmy Paterson ... You cannot mix singletons and subclasses securely. Why? The standard way of creating a singleton is with the method ... // Hold an instance of the class private static $instance; // The singleton method public static function singleton() { if (!isset(self::$instance)) { $c = __CLASS__; self::$instance = new $c; } return self::$instance; } This returns either the previously created instance or a new instance of this class. As the constructor is private (which inhibits the manual creation of the class), you cannot alter the value of $c in the example above by passing it to the function, as suggested by Scott Mattocks. Why? __construct() is private!!!! self::$instance = new $c; where $c is NOT Singleton will result in a fatal error ... Fatal error: Call to private Singleton::__construct(). You have to have __construct() as private, otherwise you can create multiple instances of the singleton, explicit contra the reason for the pattern to start with. Now. Say you do make the __construct() protected (can only be called from this class or subclasses), then you MAY have a little more success. But not much ... <?php class Singleton { // Hold an instance of the class private static $instance; // A private constructor; prevents direct creation of object protected function __construct() { echo 'I am constructed'; } // The singleton method public static function singleton($classname = __CLASS__) { if (!isset(self::$instance)) { self::$instance = new $classname; } return self::$instance; } } class SubClass extends Singleton { public static function singleton() { return parent::singleton(__CLASS__); // NOTE The singleton method MUST return an instance. } public function TellMe() { echo 'You are in here.'; } } $subclassInstance = SubClass::singleton(); $subclassInstance->TellMe(); ?> gives you ... I am constructedYou are in here. But you are not going to be able to extend this to more than 1 subclass as the singleton exists for the base class ... <?php class Singleton { // Hold an instance of the class private static $instance; // A private constructor; prevents direct creation of object protected function __construct() { echo 'I am constructed'; } // The singleton method public static function singleton($classname = __CLASS__) { if (!isset(self::$instance)) { self::$instance = new $classname; } return self::$instance; } } class SubClass extends Singleton { public static function singleton() { return parent::singleton(__CLASS__); // NOTE The singleton method MUST return an instance. } public function TellMe() { echo 'You are in here.'; } } class SubClass2 extends Singleton { public static function singleton() { return parent::singleton(__CLASS__); // NOTE The singleton method MUST return an instance. } public function TellMeMore() { echo 'You are over here.'; } } $subclassInstance = SubClass::singleton(); $subclassInstance->TellMe(); $subclass2Instance = SubClass2::singleton(); $subclass2Instance->TellMe(); ?> results in ... I am constructedYou are in here.You are in here. and NOT I am constructedYou are in here.You are over here. as you might have thought. Basically, subclassing and singletons don't really mix. ---- Manual Page -- http://www.php.net/manual/en/language.oop5.patterns.php Edit -- http://master.php.net/manage/user-notes.php?action=edit+52003 Delete: added to the manual -- http://master.php.net/manage/user-notes.php?action=delete+52003&report=yes&reason=added+to+the+manual Delete: bad code -- http://master.php.net/manage/user-notes.php?action=delete+52003&report=yes&reason=bad+code Delete: spam -- http://master.php.net/manage/user-notes.php?action=delete+52003&report=yes&reason=spam Delete: useless -- http://master.php.net/manage/user-notes.php?action=delete+52003&report=yes&reason=useless Delete: other reasons -- http://master.php.net/manage/user-notes.php?action=delete+52003&report=yes Reject -- http://master.php.net/manage/user-notes.php?action=reject+52003&report=yes Search -- http://master.php.net/manage/user-notes.php

« previous php.notes (#88168) next »