static переменная в методе и классе

berkut

Новичок
static переменная в методе и классе

Почему вот так ведёт себя пример:
PHP:
class c 
{
    protected static $obj;
    
    public function test()
    {
        static $method;
        ++$method;
        ++$this->obj;
        return array('method'=>$method, 'obj'=>$this->obj);
    }
}

$t1 = new c;
var_dump($t1->test()); // ["method"]=>  int(1),  ["obj"]=>  int(1)

$t2 = new c;
var_dump($t2->test()); // ["method"]=>  int(2),  ["obj"]=>  int(1)
Во-первых, мне _кажется_, что логичнее, что-бы было наоборот - protected static $obj - была общей для всех экземпляров класса, а static $method - была-бы своя для каждого экземпляра. Ну или в край, обе были-бы либо общими, либо своими для каждого экземпляра.
Кто знает логичное объяснение вот такому поведению?
 

berkut

Новичок
а понял, дурак.

-~{}~ 12.12.06 22:59:

а как тогда "удалить" синглтон? почему не работает это, не удаляется объект
PHP:
class singleton 
{
    public static $instance;
    
    public static function getInstance()
    {
        if (!self::$instance)
            self::$instance = new singleton;        
        return self::$instance;
    }
    
    public static function destroy($obj = null)
    {
        self::$instance = null;
        $obj = null;       
    }
    
    public function __destruct()
    {
        echo "destruct<br>\n";
    }        
    
    private function __construct()
    {
    }
}
// часть 2
$c = singleton::getInstance();
singleton::destroy($c);
echo "script end<br>\n";
// выводит script end, destruct
если вторая часть
PHP:
$c = singleton::getInstance();
//$test = singleton::getInstance(); // если раскоментировать, то unset-ить нужно и $test, тогда сработает деструктор
singleton::destroy($c);
unset ($c);
вообщем как его удалить по человечески, или синглтон на то и синглтон, что его не надо хотеть удалить?
главная непонятка в том, что если я создаю только одну ссылку на объект в $c(вторая всегда висит в self::$instance), потом вызываю destroy($c), туда передаётся ссылка на объект, присваиваю $instance и $c null, а деструктор всё равно не срабатывает.
Догнал всё как и почему работает, пока не напишешь в форум не сообразишь:)
function destroy(&$obj)
но получается, если
PHP:
$c = singleton::getInstance();
$c2 = singleton::getInstance();
то в этом случае, нужно вызывать destroy() и потом ансетить все $c, $c2 и т.д. А есть-ли способ централизованно удалить этот объехт??
 

hermit_refined

Отшельник
при том, что singleton - простейший шаблон, его удаление - довольно нетривиальная задача, особенно в C++, и особенно - когда есть несколько зависимых друг от друга синглетонов. на эту тему уже очень много написано.

в данном случае - self::$instance = null - наиболее логичный и естественный вариант. сам объект уничтожится, когда уничтожится последняя ссылка на него - путем unset() или выхода за пределы видимости. "удалить централизованно", т.е. явно вызвать деструктор из статического метода нельзя - иначе у вас в скрипте останутся разрушенные объекты.

но тут возникает другая проблема - если вы после self::$instance = null вызовете singleton::getInstance() - создастся новый объект, отличающийся от полученных ранее, и никакого синглетона уже не получается.
поэтому, если требуется - надо считать кол-во имеющихся ссылок, и уничтожать $instance (либо явно, либо неявно) только тогда, когда их больше не осталось (кроме самого self::$instance).
 

berkut

Новичок
но тут возникает другая проблема - если вы после self::$instance = null вызовете singleton::getInstance() - создастся новый объект, отличающийся от полученных ранее, и никакого синглетона уже не получается.
но в принципе, есть резон в том, что-бы его удалить, удалить раз и навсегда, без возможности его дальнейшего использования. А возможност создания нового объекта, после удаления, можно легко прикрыть.
поэтому, если требуется - надо считать кол-во имеющихся ссылок
а как это сделать?? Т.е. можно посчитать сколько раз вызвали getInstance(), но к тому времени, когда потребуется деструктор, не факт что ссылок осталось столько-же.
Вообще мысль у меня такая: допустим синглтон database, сам по себе класс жрёт память, а если в нём туча удобных, фентифлюшек, то жрёт и не мало. Например, перед формированием страницы из шаблона, эти все объекты не нужны. В то-же время формирование шаблона может занимать достаточно большое кол-во времени и памяти. Вот перед этим бы удалить всё ненужное.
 

whirlwind

TDD infected, paranoid
но в принципе, есть резон в том, что-бы его удалить, удалить раз и навсегда, без возможности его дальнейшего использования. А возможност создания нового объекта, после удаления, можно легко прикрыть.
По моему вы не совсем понимаете зачем нужен сингельтон. Самый большой прикол сингельтона в том, что он отвязывает код от конкретного класса. То есть вы можете передавать экземпляр сингельтона (грубо говоря по ссылке) и опираться на интерфейс (а не класс), вместо того, что бы вызывать статические функции и привязывать код к классу, в котором эта статическая функция реализована. Вместо кучи статических вызовов у вас всего один - getInstance. Удобства для рефакторинга очевидны.

+1 для наследования класса сингельтона придется реализовать getInstance в новом классе и все. Статические методы унаследовать нельзя.
+2 экземпляр сингельтона может быть использован в других паттернах
 

berkut

Новичок
честно говоря мало что понял. может ещё не дорос или просто ночь даёт о себе знать. было бы интересно послушать немного поподробнее, если не влом
То есть вы можете передавать экземпляр сингельтона (грубо говоря по ссылке) и опираться на интерфейс (а не класс), вместо того, что бы вызывать статические функции и привязывать код к классу, в котором эта статическая функция реализована.
Причём тут статические функции? Работать с сингельтоном, так-же как и с напрямую созданным подобным объектом. Я читал, что главная прелесть синглетона в том, что в любой точке можешь быть уверен что работаешь с _одним_ объектом, со всеми вытекающими
 

whirlwind

TDD infected, paranoid
> главная прелесть синглетона в том, что в любой точке можешь быть уверен что работаешь с _одним_ объектом, со всеми вытекающими

Правильно. А теперь перечитайте мой пост еще раз. Если написанное мною выше не ваш случай, то ничто не мешает в вашем случае использовать статические методы и статические атрибуты либо функции и глобальные атрибуты. Для этого вам не нужен экземпляр. В этом случае сингельтон для вас только лишняя заморочка.

-~{}~ 13.12.06 01:26:

PS.

> ничто не мешает в вашем случае использовать статические методы и статические атрибуты

Потому что поведение сингельтона вы изменить не сможете
 
Сверху