Лучшая практика для реализации статического наследования классов? (Singleton) - PullRequest
0 голосов
/ 14 июля 2011

Из руководства php:

[...] Вызовы статических методов разрешаются во время компиляции.При использовании явного имени класса метод уже полностью идентифицирован, и правила наследования не применяются.Если вызов сделан self, тогда self переводится в текущий класс, то есть класс, к которому принадлежит код.Здесь также не применяются правила наследования [...]

.., поэтому я ищу способ эмулировать стандарт oop наследования со статическим синглтоном.

Код объясняет лучше:

// Normal inheritance: my goal.
class Foo{
    public function test(){
        echo "Foo->test()\n";
    }
}

class Bar extends Foo{
    public function other_test()
    {
        echo "Bar->other_test()\n";
    }
}


$obj = new Bar();
echo get_class($obj) . "\n";
$obj->test();
$obj->other_test();
/*
 Output:
Bar
Foo->test()
Bar->other_test()
*/


// How i would love to do:
class Foo2{
    public static function test2()
    {
        echo "Foo2::test2()\n";
    }

    // Singleton?
    public static $_instance;
    public static function get_instance()
    {
        if(is_null(self::$_instance))
        {
            self::$_instance = new self();
        }
        return self::$_instance;
    }
}

class Bar2 extends Foo2{
    public static function other_test2()
    {
        echo "Bar2::other_test2()\n";
    }
}

$obj2 = Bar2::get_instance();
echo get_class($obj2) . "\n";
$obj2::test2();
$obj2::other_test2();
/*
 Output:
Foo2
Foo2::test2()
Fatal error: Call to undefined method Foo2::other_test2()
*/

echo "\n-------\n";

// How im doing actually:
interface Foo3{
    public static function get_instance();
}

class Bar3 implements Foo3{
    // Singleton?
    public static $_instance;
    public static function get_instance()
    {
        if(is_null(self::$_instance))
        {
            self::$_instance = new self();
        }
        return self::$_instance;
    }
    public static function test3()
    {
        echo "Bar3::test3()\n";
    }
    public static function other_test3()
    {
        echo "Bar3::other_test3()\n";
    }
}


$obj3 = Bar3::get_instance();
echo get_class($obj3) . "\n";
$obj3::test3();
$obj3::other_test3();
/*
 Output:
Bar3
Foo3::test3()
Bar3::other_test3()
*/

Последний «способ» заставляет меня избегать размещения get_instance и статических переменных в родительском классе, поэтому я не рассматриваю это каклучшее решение .. если по какой-то причине моя функция get_instance() изменится в будущем, я не хочу редактировать все классы ( наследование! наследование! мы все хотим наследование! )

Итак, есть ли способ или лучшие практики для решения этой проблемы?

ps: php5.3.2

1 Ответ

4 голосов
/ 14 июля 2011

Шаблон Singleton в PHP выглядит примерно так:

class Singleton {
     private static $instance = null;

     // Constructor is private, so class cannot be instantiazed from outside
     private function __construct() {
     }

     public static function getInstance() {
         if (static::$instance === null) {
              static::$instance = new Singleton();
         }
         return static::$instance;
     }

     public static function test() {
         echo 'Singleton::test()';
     }

     public function __sleep() {
         throw new Exception('Serialization is not alowed.');
     }

     public function __wakeup() {
         throw new Exception('Serialization is not alowed.');
     }

     public function __clone() {
         throw new Exception('Cloning is not alowed.');
     }
}

Для вас важно ключевое слово static, тогда это:

class B extends Singleton {
    public static function test2() {
         echo 'B::test2()';
    }
}

$b = B::getInstance();
B::test();
B::test2();
// Singleton::test()
// B::test()

Это то, что вы ищете?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...