Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > Вопросы по использовани. SPL


Автор: ShamanVoodoo 23.6.2013, 01:30
Код

class CountableObject implements Countable
{
    protected $_container = array('a', 'b', 'c', 'd');

    public function count()
    {
        return count($this->_container);
    }
}

$countable = new CountableObject;
var_dump(count($countable));


только сейчас задумался, а как собственно это работает?
каким образом php узнает, что при count($countable) надо вызвать метод данного объекта?!
и можно ли это применять к другим метода объекта или данное правило действует только на объекты на основе spl ?
скажем если метод class_test вызван моей функцией funct_test, то будет ли запущен этот метод?

Автор: Gromdron 23.6.2013, 17:19
Дело в том что класс CountableObject реализует интерфейс Countable, не было бы интерфейса, вы бы получили в результате - 1 обьект.

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com//object-id51c626286ccc195c06000002#findElement_E7045_51c703df6ccc19777f00037d_0

Автор: krundetz 24.6.2013, 09:25
Цитата(ShamanVoodoo @  23.6.2013,  01:30 Найти цитируемый пост)
только сейчас задумался, а как собственно это работает?

Zend API

Автор: ShamanVoodoo 24.6.2013, 14:02
Gromdron krundetz меня скорее это интересует:
Цитата

и можно ли это применять к другим метода объекта или данное правило действует только на объекты на основе spl ?
скажем если метод class_test вызван моей функцией funct_test, то будет ли запущен этот метод?


и если да, то как и какие особенности?

Автор: krundetz 24.6.2013, 15:01
Цитата(ShamanVoodoo @  24.6.2013,  14:02 Найти цитируемый пост)
и можно ли это применять к другим метода объекта или данное правило действует только на объекты на основе spl ?

можно применять к:
1. объектам spl реализующим Countable
2. собственным объектам которые реализуют Countable
3. собственным объектам которые расширяют spl объекты реализующие Countable

если изменить ваш пример так:
Код

class CountableObject
{
    protected $_container = array('a', 'b', 'c', 'd');
    public function count()
    {
        return count($this->_container);
    }
}
$countable = new CountableObject();
var_dump(count($countable));

в ответ получим:
Код

int(1) 

Автор: ShamanVoodoo 24.6.2013, 16:48
krundetz > Countable часть SPL. Речь не только о Countable, а вообще о подобном принципе:  если в объекте реализован метод, то  при вызове его одноименной функцией вместо класса подставляется результат работы метода.

печально что такой финт только для узкого круга методов на базе spl, было бы круто если бы  работало что-то подобное:
Код

function test($data)
{
    // ...
}

interface iTest
{
    public function test();
}

class myTest implements iTest
{
    public function test()
    {
        return "taadaaa";
    }
}
$test = new myTest;
var_dump(test($test)); // taadaaa


да да, знаю, вы скажете, что такое можно и самому реализовать, но не прописывать же в каждую функцию для проверки  is_object + method_exists или чего-то подобного


Автор: krundetz 24.6.2013, 17:56
Цитата(ShamanVoodoo @  24.6.2013,  16:48 Найти цитируемый пост)
было бы круто если бы  работало что-то подобное:

в том и дело, что совсем не круто

1. в вашем примере мы вместо явного вызова получаем не явный, что ухудшает читаемость кода
2. и если для итератора реализация интерфейса Countable нам позволит использовать функцию count с экземпляром класса также как с любым другим объектом языка и ожидаемый результат у нас всегда один и тот же, то в вашем примере такая реализации не несет никакой дополнительной выгоды

Есть я правильно помню в PHP есть еще несколько удачных примеров продуманной реализации данного подхода: key(), next(), rewind(), valid(), current(). Что позволяет spl итератору спокойно работать в цикле foreach.

Автор: ShamanVoodoo 24.6.2013, 23:34
krundetz

1. с этим согласен, но подобные неявные вызовы распространены повсеместно взять хоть магические методы в php, хоть триггеры в бд. они обеспечивают компактность кода, я бы посмотрел как вы тот же цикл сделали без spl...

2. мой пример это абстракция и как она работает вы знать уж точно не можете. хотите реальный пример? пожалуйста: у count есть аналог sizeof - работает он быстрее, вот только sizeof($countable) уже выполняться не будет

3. + (де)сериализация еще.. это больше похоже на заплатку, чем на продуманное решение, к __toString() можно было добавить __toArray() и обеспечить  совместимость с функциями для работы с массивами

Автор: Fortop 25.6.2013, 11:47
Цитата(ShamanVoodoo @  24.6.2013,  16:48 Найти цитируемый пост)
$test = new myTest;
var_dump(test($test)); // taadaaa

Чем это отличается от 

Код

$test->test() ;

Автор: ShamanVoodoo 25.6.2013, 15:03
Fortop> технически ничем, а практически такой вариант компактнее, проще, быстрее.  Удивился просто, что подобное решение только в качестве хинта для нескольких методов сущестует

ладно, дальше будет только флейм, так что тему можно закрывать. обидно, досадно, но ладно..

Автор: Arantir 25.6.2013, 15:38
Все просто. Есть стандартные PHP-шные фукнкции. А есть пользовательские функции. 
И чтобы не изобретать велосипед и не ухудшать читаемость кода — можно использовать стандартные в своих классах по их назначению.
А test($test) — это явное указание на то, что где-то у Вас в процедурном стиле в глобальной области описана данная пользовательская функция. Существование двойственности — возможности описания ее в классе объекта и просто в глобальной области — лишь сбиивало бы с толку.

Цитата(ShamanVoodoo @  25.6.2013,  14:03 Найти цитируемый пост)
а практически такой вариант компактнее, проще, быстрее

Технически, вариант
Код

$a->b += $c->d($n)->f($g)->t;
тоже компактнее, проще, быстрее. Но, как бы...

Автор: krundetz 27.6.2013, 11:23
Цитата(ShamanVoodoo @  24.6.2013,  23:34 Найти цитируемый пост)
2. мой пример это абстракция и как она работает вы знать уж точно не можете. хотите реальный пример? пожалуйста: у count есть аналог sizeof - работает он быстрее, вот только sizeof($countable) уже выполняться не будет

 smile 
это не конкретный пример, это бред, так как:
    1) не даны данные на которых выполняется сравнение count() и sizeof(), следовательно проверить я ничего не могу
    2) функция sizeof() является псевдонимом функции count(), тоесть быстрее она быть не может. ну никак. http://php.net/manual/ru/function.sizeof.php Да и кто вам мешает сделать так?
Код

class CountableObject implements Countable
{
    protected $_container = array('a', 'b', 'c', 'd');
    public function count()
    {
        return sizeof($this->_container);
    }
}

    3) в реализации интерфейса Countable скорость работы count() полностью зависит от программиста и его технической грамотности, ваш пример ставит под сомнение вашу техническую грамотность. Его можно переписать так:
Код

class CountableObject implements Countable
{
    protected $_container = array('a', 'b', 'c', 'd');
    protected $_count = 4;
    public function count()
    {
        return $this->_count;
    }
}

достаточно вычислять $_count только при изменение $_container, этим мы изрядно сократим количество вычислений, при условии что частота изменения меньше частоты вызова возвращения $_count, а по другому у вас и быть не может если вам важно чтобы именно этот метод работал быстрее.

Цитата(ShamanVoodoo @  25.6.2013,  15:03 Найти цитируемый пост)
а практически такой вариант компактнее, проще, быстрее.

 smile 
бред и еще раз бред
рассмотрим ваш пример:

Код

function test($data)
{
    // ...
}
interface iTest
{
    public function test();
}
class myTest implements iTest
{
    public function test()
    {
        return "taadaaa";
    }
}
$test = new myTest;
var_dump(test($test)); // taadaaa

как будет в данном случае работать интерпретатор наткнувшись на последнею строку:
1. он проверит является ли переменная $test реализацией интерфейса iTest
2. если это так, то он вызовет метод myTest::test()
3. выполнит функцию var_dump()
в случае если вызов сделать так:
Код

$test = new myTest;
var_dump($test->test());

то интерпретатор наткнувшись на последнею строку отработает так:
1. вызовет метод myTest::test()
2. выполнит функцию  var_dump()

то есть быстрее данный код быть не может по определению, так как интерпретатор выполняет на 1 действие больше.

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

компактность тоже не верна, так как проверку на соответствие переменной интерфейсу вам тоже надо где то выполнить.

Ставлю вам минус за упертость в своей технической безграмотности.



Автор: krundetz 27.6.2013, 13:26
Цитата(ShamanVoodoo @  24.6.2013,  23:34 Найти цитируемый пост)
3. + (де)сериализация еще.. это больше похоже на заплатку, чем на продуманное решение, к __toString() можно было добавить __toArray() и обеспечить  совместимость с функциями для работы с массивами

для совместимости работы с массивами существуют другие методы и интерфейс, в одном из своих ответов в этой теме я их упоминал

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)