Объясните дураку ооп. Видимость переменных в разных инстансах.

fixxxer

К.О.
Партнер клуба
__unset не поможет. Я так понимаю, код примерно такой:

PHP:
class C {

    protected $foo = 'foo';

    protected $data = [];

    public function test() {
        var_dump($this->foo);
        unset($this->foo);
        // now everything goes to magic methods
        var_dump($this->foo);
        $this->foo = 'bar';
        var_dump($this->foo);
    }

    public function __get($k) {
        if (!array_key_exists($k, $this->data)) {
            throw new OutOfBoundsException;
        }

        return $this->data[$k];
    }

    public function __set($k, $v) {
        $this->data[$k] = $v;
    }

    public function __unset($k) {
        unset($this->data[$k]);
    }

}

$c = new C;
$c->foo = 'bazz';
$c->test();
var_dump($c->foo);
Код:
$ php test.php 
string(3) "foo"
string(4) "bazz"
string(3) "bar"
string(3) "bar"
В общем, правильное решение одно - НЕ ДЕЛАТЬ ТАК.
 

Вурдалак

Продвинутый новичок
Делать-то так делать нельзя, но если речь идет о теоретическом «восстановлении» свойств, то оно возможно:
PHP:
class A {
    private $foo = 'foo';

    public function __construct() {
        unset($this->foo);
        var_dump($this);
        $this->foo = 'blabla';
        var_dump($this);
    }

    public function __set($k, $v) {
        if ($k === 'foo') { 
            $this->foo = $v;
        } else {
            echo 'woot?', PHP_EOL;
        }
    }
}

class B {
    protected $foo = 'foo';

    public function __construct()
    {
        unset($this->foo);
        var_dump($this);
        $this->foo = 'blabla';
        var_dump($this);
    }   

    public function __set($k, $v) {
        if ($k === 'foo') { 
            $this->foo = $v;
        } else {
            echo 'woot?', PHP_EOL;
        }
    }
}

new A;
new B;
Код:
object(A)#1 (0) { }
object(A)#1 (1) { ["foo:private"]=> string(6) "blabla" }
object(B)#1 (0) { }
object(B)#1 (1) { ["foo:protected"]=> string(6) "blabla" }
 

Вурдалак

Продвинутый новичок
Жесть или нет — без разницы, я говорю, что свойство можно восстановить. Тьфу, еще раз на подобную тему с вами общаться.
 

fixxxer

К.О.
Партнер клуба
Жесть или нет — без разницы, я говорю, что свойство можно восстановить.
Можно, но если кто-то напишет такое вместо замены unset на присваивание null, за это следует отрывать руки ;)
Тьфу, еще раз на подобную тему с вами общаться.
Да ладно тебе )
 

Redjik

Джедай-мастер
ну тогда уж стоит отрывать руки за unset объявленного свойства, ибо оно изначально null, если не было присвоения при инициализации
 

fixxxer

К.О.
Партнер клуба
Кстати, property_exists после unset() продолжает возвращать true. Этот факт выносит мне мозг, но это так. Этим можно воспользоваться, но не могу придумать неизвращенного способа, как отличить внутренний вызов __set от внешнего.
 

fixxxer

К.О.
Партнер клуба
Чем дальше лезешь в тонкости PHP, тем больше он поражает. :)

PHP:
class C {

    protected $foo = 'foo';

    public function test() {
        unset($this->foo);

        $foo = (new ReflectionClass($this))->getProperty('foo');
        $foo->setAccessible(true); // без этого не даст сходить в protected - ну что ж, логично
        $foo->setValue($this, 'foo'); // вот это сейчас пойдет и дернет, мать его за ногу, __set
        $foo->setAccessible(false);

        var_dump($this->foo);
    }

    public function __set($k, $v) {
        var_dump("__set $k=$v");
    }

}

(new C)->test();
Код:
$ php 0.php 
string(13) "__set foo=foo"
PHP Notice:  Undefined property: C::$foo in /home/fixxxer/tmp/0.php on line 14
NULL
Arghhhhhh!
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Рефлексия - вообще дисциплина из школы черной магии, тут ничего не стоит ждать заранее.
 

MiksIr

miksir@home:~$
А зачем делать unset? присваивай null
Да случайно, хотел объект грохнуть, который был свойству присвоен и вместо $this->property = null сказал unset. А когда пытался пересоздать его типа $this->property = new Object - получил от Yii привет, типа нет такого свойства ;)
 

cDLEON

Онанист РНРСlub
Ragazzo
Чё? А зачем нужны тогда все эти "late static bindings"? Я, кстати, баг репорт по этому поводу писал. Сказали, что это "фича".
Вообще, я вижу, что вас вполне вся эта ситуация устраивает. Потому как на любой мой довод, что с языком становится что то не то, находится человек, который обязательно скажет: "Всё ок парень, ты просто не умеешь его готовить". Это печально.
 

fixxxer

К.О.
Партнер клуба
cDLEON
Это фича, объяви в B static $a и все будет хорошо.

Поясняю, почему фича:

PHP:
class A {
  static $a;
}

class B extends A {
  static $a;
}

class C extends B { }
Я хочу static $a sharing между C и B, но разные в B и A. Фича позволяет это сделать.
 

cDLEON

Онанист РНРСlub
fixxxer
Я знаю это. А теперь я объясню почему это бредовая фича. Потому, что для разработчика, который начнёт читать этот код, будет совсем не понятно откуда в B берётся переменная вообще. Ведь её ни кто не инициализирует. А ведь "наследников" то может быть совсем не один. Кто от твоей фичи выигрывает ровным счётом ????? Шаринг делается совсем другими, хорошо читаемыми, методами.
 

fixxxer

К.О.
Партнер клуба
Эти соображения имеют смысл, можно согласиться (хотя есть аргументы в обе стороны). Но надо было высказывать эти соображения при разработке LSB - во время ранних dev-сборок php 5.3. Сейчас уже поздно, потому что если и согласиться с твоими доводами, это BC break.
 

fixxxer

К.О.
Партнер клуба
Рефлексия - вообще дисциплина из школы черной магии, тут ничего не стоит ждать заранее.
Я все же считаю это багом (тем более - это довольно хитрая ситуация, и такой баг пропустить не просто - а очень просто): ReflectionProperty - это "вещь в себе", она не должна триггерить __set.

Зарепорчу, пожалуй.

UPD: зарепортил
 

fixxxer

К.О.
Партнер клуба
А для меня :: это статический вызов.
Но слева находится объект. К какому же тогда классу идет обращение? Это конечно неразрешимая загадка.
http://www.php.net/manual/en/language.oop5.static.php написал(а):
As of PHP 5.3.0, it's possible to reference the class using a variable.
...
PHP:
$foo = new Foo();
print $foo::$my_static . "\n";
В мане это хреново описано (показан пример и все), но по сути - это то же, что:
PHP:
$foo = new Foo();
$className = get_class($foo);
print $className::$my_static . "\n";
Сабжевое поведение вообще очень плохо описано, но можно понять логику из Example 3.

Вообще, конечно, надо на это заводить documentation problem bug.

(Кстати, LSB это вообще не ООП. Нет такого в ООП. Ни в одном языке нет такого, кроме PHP. Это такой хак, но - следует признать - удобный хак).
 

cDLEON

Онанист РНРСlub
Кстати, LSB это вообще не ООП. Нет такого в ООП. Ни в одном языке нет такого, кроме PHP. Это такой хак, но - следует признать - удобный хак
Ну LSB, возможно нет, но вот наиболее удачных вариантов, которые будут решать такие же задачи - хватает. В том же python это декоратор classmethod
 

Ragazzo

TDD interested
cDLEON
в том же питон декоратор это функция, и чо? теперь надо в похапе все тащить чтоли? есть что есть :S
 
Сверху