php 5-3, late-static-binding

crocodile2u

http://vbolshov.org.ru
php 5-3, late-static-binding

Играюсь с новой версией языка. Вот смотрите, какая штука:

Код:
<?php

class Foo {
    static protected $p = 1;
    static function setP($p)
    {
		static::$p = $p;
    }
    static function printP()
    {
    	echo get_called_class() . '::$p : ' . static::$p . "\n";
    }
}

class Bar extends Foo {
}

class Baz extends Foo {
}

Foo::printP();
Bar::printP();
Baz::printP();

Bar::setP(2);

Foo::printP();
Bar::printP();
Baz::printP();

?>
Вот что этот код выводит:

Код:
Foo::$p : 1
Bar::$p : 1
Baz::$p : 1
Foo::$p : [b]2[/b]
Bar::$p : [b]2[/b]
Baz::$p : [b]2[/b]
Между тем, на мой взгляд, было бы логичнее, если вывод был таким:

Код:
Foo::$p : 1
Bar::$p : 1
Baz::$p : 1
Foo::$p : 1
Bar::$p : [b]2[/b]
Baz::$p : 1
Мне кажется, логичнее было бы в данном случае изменять значение статического свойства для того класса, у которого вызывается метод setP() - и его потомков. Что думаете по этому поводу Вы?

ЗЫ. Если объявить static protected $p; в каждом из классов, унаследованных от Foo - поведение меняется, и, насколько я понимаю, объявляя или "умалчивая" это свойство - можно добиться того поведения, которое мне кажется логичным.
 

crocodile2u

http://vbolshov.org.ru
whirlwind
?

dr-sm
Мне, например, это нужно для реализации следующего механизма: есть АктивнаяЗапись (базовый класс - ActiveRecord) а-ля Руби-он-Рейлз, т. е. методы работы с таблицей - статические, методы работы с рядом - методы объекта. Хочу устанавливать режим выборки результатов (fetchMode) - для каждого класса активной записи по отдельности с помощью вызова MyActiveRecord::setFetchMode(). Но пока что получается, что MyActiveRecord::setFetchMode() - поменяет fetchMode для всех классов - наследников АктивнойЗаписи. А хотелось бы, чтобы MyActiveRecord::setFetchMode() - поменял бы режим прокрутки только для MyActiveRecord, и никак не затронул бы, допустим, MyAnotherActiveRecord.

-~{}~ 14.05.08 13:15:

whirlwind
По-моему, ты не совсем вникаешь в суть вопроса, но прокомментировать шанса не упускаешь. Просьба к модераторам убрать из темы мусор.
 

whirlwind

TDD infected, paranoid
crocodile2u по моему ты сам не вникаешь в суть своего вопроса. Для начала ответь, почему поведение меняется на ожидаемое, когда ты делаешь

объявить static protected $p; в каждом из классов, унаследованных от Foo - поведение меняется
 

crocodile2u

http://vbolshov.org.ru
master_x
Это, блин, сверхинформативное сообщение. Молодец, возьми с полки пирожок.

Всем:
В принципе, поразмыслив еще над этим кодом и посовещавшись с друзьями (спасибо, StUV), я пришел к выводу, что вариант, реализованный в языке сейчас - прозрачнее, чем то поведение, которое я ожидал увидеть. И тем не менее, тема для меня лично сохраняет интерес, и очень бы хотелось услышать аргументированные доводы pro & contra.
 

dr-sm

Новичок
LSB is not LSD :D

вобще-то с каноническим ООП фича сея нестыкуется как-то, имхо.
как может static binding быть late,
и late binding - static,
алиса в стране чудес ))
 

whirlwind

TDD infected, paranoid
dr-sm Да эта фича нужна любителям propelоподобных ормов. Кастрированное расширение статических методов, в целях сокращения объема кода не в ущерб импрессивности.
 

crocodile2u

http://vbolshov.org.ru
whirlwind
Я-то как раз провел за тестами пару часов, и могу сказать, почему я ожидал другого поведения от написанного кода: именно по причине использования ключевого слова "static" вместо привычного "self". И то, что "поведение меняется на ожидаемое, когда ты делаешь static protected $p; в каждом из классов" - как раз заслуга этого самого late-static-binding. И реализация могла бы быть как такой, как она есть - так и такой, какую я сначала ожидал увидеть.
 

whirlwind

TDD infected, paranoid
crocodile2u главное, что нужно помнить - статика не наследуется. Все эти потуги нацелены на то, что бы добавить гибкости в код, обильно юзающий статику.
 

crocodile2u

http://vbolshov.org.ru
whirlwind
Моя реализация ActiveRecord - открыта и ты можешь посмотреть на ее код. Ничего похожего на пропель ты там не найдешь.

dr-sm
LSB - полезная фича, которую предоставляет язык. И то, что я не один такой, кто хочет эту фичу использовать (например, см. http://framework.zend.com/wiki/display/ZFPROP/Zend_Db_ActiveRecord) - лишний раз подтверждает, что фича эта не лишена привлекательности.

-~{}~ 14.05.08 14:01:

whirlwind
Согласен, злоупотреблять статикой не стоит. Но, например, тот же ActiveRecord приобретает просто замечательно красивый вид (ок, на мой взгляд) при использовании нескольких статических методов.
 

whirlwind

TDD infected, paranoid
Моя реализация ActiveRecord - открыта и ты можешь посмотреть на ее код. Ничего похожего на пропель ты там не найдешь.
Я имею в виду множество различных *::findBy . Я не вижу особой необходимости в такого вида выразительности. От этого сильно страдает гибкость кода. Почему например не вот так

PHP:
$user = new User();
$user->findBy...

// или 

$users = $user->getIterator()->findBy...
 

Gas

может по одной?
RoR нынче в моде, когда сам поглядел на LSB, сразу же подумалось об использовании его в для active record в стиле rails :)
 

crocodile2u

http://vbolshov.org.ru
whirlwind
Хотя бы потому, что семантически более приближенной к структуре СУБД выглядит

PHP:
<?php
$user = User::find();
?>
-~{}~ 14.05.08 14:11:

И кстати, почему гибкость кода-то страдает?

Черт!
Я сам не заметил, как от темы мы отскочили на холивар по поводу самого late-static-binding. Господа, просьба высказываться по теме, у кого есть что сказать...
 

cDLEON

Онанист РНРСlub
Хм :)
Интересная фича )))
Конфиги можно грузить в родителя 8)
 

whirlwind

TDD infected, paranoid
> более приближенной к структуре СУБД выглядит

Чем? Отсутсвием $ и -> вместо :: ?

PHP:
$user->find();
Это все стереотипы.

Я не знаю, имеет ли смысл обсуждать уже не раз обсужденное.
Сколько design patterns вы можете примернить к статике? Будем юзать велосипеды или хаки?
 

Alexandre

PHPПенсионер
на мой взгляд оно правильно выводит:
Код:
Foo::$p : 1
Bar::$p : 1
Baz::$p : 1
Foo::$p : 2
Bar::$p : 2
Baz::$p : 2
меняется переменная базового класса.
 

atv

Новичок
Лично для меня, если бы работала конструкция new User()->find(), то мне не нужно было бы LSB.

Что касается вопроса, для меня поведение вполне ожидаемое, то что статическое свойство разделяется всеми экземплярами класса и наследников класса. И, вполне естественно для меня, что переопределяя статическое свойство в наследнике, оно уже не разделяется наследниками родительского класса.
 
Сверху