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


Автор: gcc 22.7.2009, 02:58
объясните плиз как его использовать и для чего он нужен?

это для множественного наследования?

http://search.cpan.org/~flora/NEXT-0.64/lib/NEXT.pm
http://search.cpan.org/~flora/Class-C3-Adopt-NEXT-0.12/lib/Class/C3/Adopt/NEXT.pm
http://search.cpan.org/~flora/Class-C3-0.21/lib/Class/C3.pm

что за чем должно идти?

наприер NEXT.pm отличается не много от Class::C3::Adopt::NEXT 


Код

        $self->NEXT::DISTINCT::method();



Код

        $self->NEXT::ACTUAL::DISTINCT::method();
        $self->NEXT::DISTINCT::ACTUAL::method();


Код

    sub a_method {
        my ($self) = @_;
        # Do some stuff

        # Re-dispatch method
        # Note that this will generate a warning the _first_ time the package
        # uses NEXT unless you un comment the 'no warnings' line above.
        $self->NEXT::method();
    }


прчему тут не написали SUPER?  NEXT ищет ближайщий методв  a_method по наследованию?

   
Код

 sub yourmethod {
        my $self = shift;

        # $self->NEXT::yourmethod(@_); becomes
        $self->maybe::next::method();
    }

    sub othermethod {
        my $self = shift;

        # $self->NEXT::ACTUAL::yourmethodname(); becomes
        $self->next::method();
    }



maybe это класс? 
ACTUAL - это текущий класс?

Автор: gcc 5.12.2009, 23:13
подскажите опять есть такой код:

Код

package Catalyst::Plugin::Upload::Image::Magick;

use strict;
use warnings;

use Catalyst::Request::Upload::Image::Magick;

sub prepare_uploads {
  my $c = shift;

  $c->maybe::next::method(@_);



maybe::next::method - это тоже самое что и NEXT::ACTUAL::yourmethodname()

но что делает данный код и в чем разнциа между maybe::next::method(); и $self->next::method(); ?

http://search.cpan.org/~flora/Class-C3-Adopt-NEXT-0.12/lib/Class/C3/Adopt/NEXT.pm#Current_code_using_NEXT

т.е. это деревовидное наследование в 2 ветки?

Автор: vadiml 25.12.2009, 13:08
Я, кстати, тоже присоединяюсь к вопросу чем NEXT лучше SUPER.

Автор: Bulat 25.12.2009, 17:11
Опять же, я не сильный любитель приемов ООП в перл, но рискну предположить...

"Обход дерева в глубину"  smile 

Т.е. если super - вызывает метод только у текущего предка, то next - вызывает методы у всех предков по иерархии..

при множественном наследовании, по правилу "кто первый тот и прав", то использование next - позволяет вызвать все методы всех предков с аналогичным именем.. ну и всякое шаманство там в случае с ромбовидной иерархией, шоп метод одного и того же класса не вызывался дважды - distinct

every - аналогичное, но только с правилом кто первый тот и прав, по-моему....

Кажется... смысл оного конечно лично мне мало понятен, ибо так на вскидку трудно предположить ситуацию в которой была бы необходимость вызывать все методы всех предков, а не только последний переопределенный. Да и я считаю, что такое написание - наследование в несколько уровней с переопределением, - не есть хороший тон.. уж если метод так актуален, вынеси его в отдельный абстрактный класс и юзай полиморфизм. smile

Автор: Bulat 25.12.2009, 17:41
P.S. Т.е. обход дерева в ширину  smile 

Автор: gcc 25.12.2009, 18:47
а чем отличается   $c->maybe::next::method(@_);  от  $c->next::method(@_); ?

не могу перевести с английского
http://search.cpan.org/~flora/Class-C3-Adopt-NEXT-0.12/lib/Class/C3/Adopt/NEXT.pm#Current_code_using_NEXT

Добавлено @ 18:55
vadiml, там написано что лучше использовать next (Class::C3::Adopt::NEXT  и аналогичные на Си), а не NEXT, так как линеризация происхоит медленно если много классов в большой программе

а в чем разница между SUPER так и не понял...

но в единственном случе пришлось использовать next в посте выше....


автор модуля Damian Conway в свой книге (perl OOP 2000г) писал про эту проблему с SUPER (книга 1200 страниц я пытался найти абзац где это написано, но не нашел), и в книге "Рецепты для профессионалоов" не помню какое издание, но там написано было что если множественное наследование, то надо как-то придумать с SUPER, чтобы вызвать только с какого-то класса... оно как бы не удобно....


по-моиму SUPER ищет слева на права в массиве @ISA, а NEXT справа на лево, или наоброт :(

Автор: Bulat 26.12.2009, 13:43
Не знаю ))

То, что я написал и то лишь предположение, и может быть ошибочное как полностью, так и отчасти smile

Тут надо брать один и тот же тест и проделать его с super, c next и смотреть разницу в поведении.. Иногда понять те или иные программистские решения бывает очень сложно smile

Автор: Vaneska 26.12.2009, 20:14
Для super
Код

#!/usr/bin/perl

package ClassA;
    sub new {bless( {}, shift); }
    sub func { print "A\n"; }

package ClassB;
    use base 'ClassA';
    sub func {
        my $self = shift;
        print "B\n";
        $self->SUPER::func();
    }

package ClassC;
    use base 'ClassA';
    sub func {
        my $self = shift;
        print "C\n";
        $self->SUPER::func();
    }

package ClassD;
    use base qw(ClassB ClassC);
    sub func {
        my $self = shift;
        print "D\n";
        $self->SUPER::func();
    }

package main;

ClassD->new->func();



Для next
Код

#!/usr/bin/perl

#use NEXT;
use Class::C3::Adopt::NEXT;

package ClassA;
    sub new { bless( {}, shift); }
    sub func { print "A\n"; }

package ClassB;
    use base 'ClassA';
    sub func {
        my $self = shift;
        print "B\n";
        $self->NEXT::func();
    }   
    
package ClassC;
    use base 'ClassA';
    sub func { 
        my $self = shift;
        print "C\n"; 
        $self->NEXT::func();
    }   
    
package ClassD;
    use base qw(ClassB ClassC);
    sub func { 
        my $self = shift;
        print "D\n"; 
        $self->NEXT::func();
    }   
package main;

ClassD->new->func();



В результате получаем:
SUPER: D B A
NEXT:     D B C A

С помощью NEXT мы выполняем все функции func в дереве наследовения слассов.
А SUPER такого не делает.

Получается, что NEXT - полноценная поддержка множественного наследования.



Автор: Bulat 28.12.2009, 17:50
Цитата(Vaneska @  26.12.2009,  20:14 Найти цитируемый пост)
В результате получаем:
SUPER: D B A
NEXT:     D B C A


Значит все же в ширину smile Только по твоему примеру, мне казалось что при NEXT 'A' - должен был бы появится дважды, так как он является родителем и для 'C' и для 'B'. И единственный способ обойти это при NEXT , юзать NEXT::DISTINCT... Хотя, может быть я ошибаюсь...

Автор: Vaneska 28.12.2009, 18:29
Цитата(Bulat @  28.12.2009,  17:50 Найти цитируемый пост)
Значит все же в ширину smile Только по твоему примеру, мне казалось что при NEXT 'A' - должен был бы появится дважды, так как он является родителем и для 'C' и для 'B'. И единственный способ обойти это при NEXT , юзать NEXT::DISTINCT... Хотя, может быть я ошибаюсь...

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

В общем надо доку почитать и код посмотреть, сразу все ясно будет smile

Автор: Bulat 29.12.2009, 11:11
Цитата(Vaneska @  28.12.2009,  18:29 Найти цитируемый пост)
В общем надо доку почитать и код посмотреть, сразу все ясно будет


не, судя по всему, из того что я прочел на cpan'е, именно этот трабл с двойным вызовом одной и той же функции одного и того же экземпляра класса при ромбовидной иерархии - четко описывался и для обхода оного именно юзалась конструкция с DISTINCT

http://search.cpan.org/~flora/NEXT-0.64/lib/NEXT.pm

Код

Avoiding repetitions

If NEXT redispatching is used in the methods of a "diamond" class hierarchy:
....

(i.e. A::foo is called twice).

In some cases this may be the desired effect within a diamond hierarchy, but in others (e.g. for destructors) 
it may be more appropriate to call each method only once during a sequence of redispatches.

To cover such cases, you can redispatch methods via:

        $self->NEXT::DISTINCT::method();


а уж совсем устанавливать либу себе и в ней ковырятся действительно ниохота smile

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