ФорумПрограммированиеPHP для идиотов → Копирование метода

Копирование метода

  • Абырвалг

    Сообщения: 6476 Репутация: N Группа: Джедаи

    Spritz 10 января 2010 г. 17:23

    Можно ли как-то "на ходу" к объекту добавить 1-2 метода? А еще лучше скопировать их из другого объекта. И предел мечтаний, что б это были protected методы
  • phpdude

    Сообщения: 26624 Репутация: N Группа: в ухо

    Spritz 10 января 2010 г. 17:33, спустя 9 минут 33 секунды


    Можно ли как-то "на ходу" к объекту добавить 1-2 метода? А еще лучше скопировать их из другого объекта. И предел мечтаний, что б это были protected методы
    $obj->newfunc = create_function('$x',' echo $x;');

    такое не катит? если нет, посмотри в сторону рефлексии может можно чтото сделать
    Сапожник без сапог
  • Абырвалг

    Сообщения: 6476 Репутация: N Группа: Джедаи

    Spritz 10 января 2010 г. 18:44, спустя 1 час 11 минут 21 секунду

    не, нужно из объекта их вытянуть. С рефлексией не работал и толковых руководств с примерами не встречал (окромя как получать информацию о классах)
    Спустя 162 сек.
    есть расширение в PECL для этого

    upd: вот оно http://www.php.net/manual/en/function.runkit-method-copy.php
  • NRG

    Сообщения: 4761 Репутация: N Группа: в ухо

    Spritz 10 января 2010 г. 18:19, спустя 23 часа 35 минут 24 секунды

    Можно ли как-то "на ходу" к объекту добавить 1-2 метода? А еще лучше скопировать их из другого объекта

    Абырвалг, если не секрет, то какова должна быть суть этих методов ?
    что ты пытаешся сделать ?
  • Абырвалг

    Сообщения: 6476 Репутация: N Группа: Джедаи

    Spritz 10 января 2010 г. 18:32, спустя 12 минут 56 секунд

    множественное наследование protected-методов. Суть такова:

    Занимаюсь социалкой. Там есть свой форум (допустим class Module_Forum). Есть также группы (class Module_Groups). В группах есть форум (class Module_Groups_Forum). В последнем классе мне нужно наследовать общий форум и переписать пару методов (getToken, getRedirectUrl и проверить, есть ли пользователь в группе). Кроме того есть несколько методов от класса Module_Groups, которые тоже должны присутствовать.

    Короче покопаю в сторону ReflectionMethod::invokeArgs. Ну или попробую пересмотреть архитектуру.
    Спустя 56 сек.
    да, я гуглил на эту тему, везде просто подряд пытаются вызвать методы классов-родителей, даже не проверяя их видимость.
  • phpdude

    Сообщения: 26624 Репутация: N Группа: в ухо

    Spritz 10 января 2010 г. 19:11, спустя 39 минут 5 секунд

    протектеды копируешь в наследников? … они разве так недоступны? эм
    Сапожник без сапог
  • Абырвалг

    Сообщения: 6476 Репутация: N Группа: Джедаи

    Spritz 10 января 2010 г. 19:28, спустя 16 минут 35 секунд

    нужно так:
    родитель1
    протектед11
    родитель2
    протектед22

    ребенок наследуй родителя1 и родителя2
  • artoodetoo

    Сообщения: 5139 Репутация: N Группа: в ухо

    Spritz 11 января 2010 г. 2:21, спустя 6 часов 53 минуты 1 секунду

    может быть тебе поможет техника "настраиваи…маи…ваемого поведения"  см. yii framework


    Поведение компонента

    Начиная с версии 1.0.2, к компоненту была добавлена поддержка примесей (mixin) и теперь к компоненту можно прикрепить одно или несколько поведений. Поведение — это объект, чьи методы могут быть «унаследованы» компонентом, к которому прикреплены, посредством объединения функционала вместо четкой специализации (как в случае обычного наследования класса). К компоненту можно прикрепить несколько поведений и таким образом получить множественное наследование.

    http://www.yiiframework.com/doc/guide/ru/basics.component
    Спустя 96 сек.
    p.s. не уверен, что экспортируемые методы могут быть protected, но поковыряй. может чего пригодится
    p.p.s. ну так как в yii все компоненты наследуются от "корневого" класса, то вероятно — да, можно protected
    p.p.p.s. интересно было бы обсудить твоё управление правами доступа. сильно интересуюсь такими вещами.
    ιιlllιlllι унц-унц
  • Абырвалг

    Сообщения: 6476 Репутация: N Группа: Джедаи

    Spritz 11 января 2010 г. 2:46, спустя 24 минуты 38 секунд

    может быть тебе поможет техника "настраиваи…маи…ваемого поведения" см. yii framework

    да, очень может быть. Я вчера нашел аналогичное от Симфони ман: http://www.symfony-project.org/book/1_0/17-Extending-Symfony , код: http://trac.symfony-project.org/browser/branches/1.4/lib/plugins/sfPropelPlugin/lib/addon/sfMixer.class.php

    p.s. не уверен, что экспортируемые методы могут быть protected, но поковыряй. может чего пригодится

    надеюсь на это, проверю

    p.p.p.s. интересно было бы обсудить твоё управление правами доступа. сильно интересуюсь такими вещами.

    прав доступа еще нету. Пока писать могут только участники группы. А создатель группы может тереть их сообщения.
  • artoodetoo

    Сообщения: 5139 Репутация: N Группа: в ухо

    Spritz 11 января 2010 г. 3:36, спустя 50 минут 21 секунду

    Абырвалг, приглашаю в новую тему для обсуждения прав. наверное у тебя есть какие-то идеи.
    ιιlllιlllι унц-унц
  • Абырвалг

    Сообщения: 6476 Репутация: N Группа: Джедаи

    Spritz 11 января 2010 г. 8:20, спустя 4 часа 44 минуты 9 секунд

    да, тему ту обсудим.
    Через рефлексию вызвать протектед нельзя

    <?php

    class A
    {
    public function __construct() {}

    public function ma()
    {
    echo "call A->ma\n";
    }

    protected function m()
    {
    echo "call A->m\n";
    }
    }

    class B
    {
    public function __construct() {}

    protected function mb()
    {
    echo "call B->ma\n";
    }

    protected function m()
    {
    echo "call B->m\n";
    }
    }

    class AB
    {
    protected $objects = array();

    public function __construct()
    {
    $this->objects[] = new A;
    $this->objects[] = new B;
    }

    public function __call($method, $args)
    {
    foreach ($this->objects as &$object) {
    if (method_exists($object, $method)) {
    $m = new ReflectionMethod(get_class($object), $method);
    return $m->invokeArgs($object, $args);
    //return call_user_func_array(array($object, $method), $args);
    }
    }
    die('Method ' . $method . ' doesn\'t exists');
    }
    }

    $object = new AB();
    $object->ma();
    $object->mb();
    $object->m();


    call A->ma
    <!–error–><br />
    <b>Fatal error</b>: Uncaught exception 'ReflectionException' with message 'Trying to invoke protected method B::mb from scope ReflectionMethod' in Z:\home\localhost\*\index.php:54
    Stack trace:
    #0 Z:\home\localhost\*\index.php(54): ReflectionMethod->invokeArgs(Object(B), Array)
    #1 [internal function]: AB->__call('mb', Array)
    #2 Z:\home\localhost\*\index.php(64): AB->mb()
    #3 {main}
    thrown in <b>Z:\home\localhost\*\index.php</b> on line <b>54</b><br />
    <script language=JavaScript src='/errors/phperror_js.php'></script>




    Но есть у меня одна идейка как это обойти…
  • phpdude

    Сообщения: 26624 Репутация: N Группа: в ухо

    Spritz 11 января 2010 г. 8:27, спустя 6 минут 42 секунды

    а ты думал что можно просто так вызвать метод протектед из класса который не наследует владельца метода? хуйна 100% получится и получилась

    да и вообще я думал что ты хочешь именно УНАСЛЕДОВАТЬ двух родителей, а ты просто "адаптер" с небольшими изменениями реализуешь.

    зы рефлексия для того, что ты делаешь даже не нужна обычный call_user_func_arr будет работать почти уверен что быстрее и будет работать, для протектедов естественно нет, и не должен
    Сапожник без сапог
  • Абырвалг

    Сообщения: 6476 Репутация: N Группа: Джедаи

    Spritz 11 января 2010 г. 8:50, спустя 23 минуты 4 секунды

    ну ты видел мою простыню кода? там же так:
    return $m->invokeArgs($object, $args);
    //return call_user_func_array(array($object, $method), $args);


    просто я думал, что рефлексия - это такая особая хуйня, которая может абсолютно все. Оказалось, что нет.

    про адаптеры: вот мне именно нужно унаследовать. Я не понимаю тех людей, которые пишут мануалы по множественному наследованию, где они вызывают паблик методы. Нахрена мне наследовать паблик методы тогда? я ж могу сам экземпляр класса создать и обращаться к нему
  • phpdude

    Сообщения: 26624 Репутация: N Группа: в ухо

    Spritz 11 января 2010 г. 8:53, спустя 3 минуты 5 секунд

    просто я думал, что рефлексия - это такая особая хуйня, которая может абсолютно все. Оказалось, что нет.
    аха, и зенд обходить из prepend_file файла … рефлексия ваще мега штука! чо хочешь, то и делаешь!

    нет конечно. посмотреть список и информацию о объектах можно, а делать что угодно с ними … нахуй тогда вообще вводить все эти приваты, протектеды и прочие глупости, ага? :)
    Спустя 49 сек.
    про адаптеры: вот мне именно нужно унаследовать. Я не понимаю тех людей, которые пишут мануалы по множественному наследованию, где они вызывают паблик методы. Нахрена мне наследовать паблик методы тогда? я ж могу сам экземпляр класса создать и обращаться к нему
    вот тут ты прав. я вообще ненавижу людей которые пишут хуйню, которую минимум не понимают
    Сапожник без сапог
  • Абырвалг

    Сообщения: 6476 Репутация: N Группа: Джедаи

    Spritz 11 января 2010 г. 9:37, спустя 44 минуты 32 секунды

    Вха-ха! написал прототип. С первого раза скомпилировалось и отработало с ожидаемыми результатами:


    // родитель, которого собираются наследовать должен реализовывать этот интерфейс
    interface MultipleInheritanceInterface
    {
    //TODO: methods for __get, __set
    public function invoke($method, $args);
    }
    // если вам лень реализовывать этот интерфейс - просто наследуйте этот класс
    abstract class MultipleInheritanceBase implements MultipleInheritanceInterface
    {
    // через этот метод мы будем вызывать protected-методы
    public function invoke($method, $args)
    {
    call_user_func_array(array($this, $method), $args);
    }
    }
    // а этот класс должен наследовать потомок
    abstract class MultipleInheritance
    {
    private $objects = array();
    //TODO: public?
    final protected function extend($object)
    {
    if (! $object instanceof MultipleInheritanceInterface)
    throw new Exception();

    $this->objects[get_class($object)] = $object;
    }

    public function __call($method, $args)
    {
    foreach ($this->objects as &$object) {
    if (method_exists($object, $method)) {
    return call_user_func_array(array($object, 'invoke'), array($method, $args));
    }
    }
    throw new Exception('Method ' . $method . ' doesn\'t exists');
    }
    }


    тесты:

    // первый родитель. Интерфейс не реализовываю, просто наследую уже готовую реализацию
    class A extends MultipleInheritanceBase
    {
    public function __construct() {}

    public function ma()
    {
    echo "call A->ma\n";
    }

    protected function m()
    {
    echo "call A->m\n";
    }
    }
    // второй родитель
    class B implements MultipleInheritanceInterface
    {
    public function __construct() {}
    // самостоятельно реализовываю интерфейс
    public function invoke($method, $args)
    {
    echo "call B->invoke\n";
    call_user_func_array(array($this, $method), $args);
    }

    protected function mb()
    {
    echo "call B->mb\n";
    }

    protected function m()
    {
    echo "call B->m\n";
    }
    }

    class AB extends MultipleInheritance
    {
    public function __construct()
    {
    // наследываю классы.
    $this->extend(new A);
    // класс
    $this->extend(new B);
    }

    protected function pmab()
    {
    echo "call AB->pmab\n";
    }

    public function mab()
    {
    $this->pmab();
    echo "call AB->mab\n";
    }
    }

    $object = new AB();
    $object->ma(); // public
    $object->mb(); // protected
    $object->m(); // protected overloaded
    $object->mab(); // public, свой


    есть небольшой баг: сейчас у нас FIFO, а нужно сделать стек. Мы сначала наследовали A а потом B. Класс B переписал метод m, но выполнился m из A.
    Кроме того нужно реализовать поддержку полей. Но мне лень.

Пожалуйста, авторизуйтесь, чтобы написать комментарий!