2012-06-03 17 views
7

Czy istnieje standardowy CPAN sposób na poznanie wszystkich nadklas klas Perla (lub lepiej jeszcze całego drzewa nadklasy, aż do UNIWERSALNEJ)?Jaki jest najlepszy sposób na poznanie wszystkich klas nadrzędnych klasy Perl?

Czy jest to najlepsza praktyka, aby po prostu sprawdzić @{"${$class}::ISA"} dla każdej klasy, rodziców klasy itp ...?

+1

Czy to może być podstępne pytanie, na które odpowiedź brzmi: nie chcesz tego robić? Czasami powinieneś pozwolić, aby polimorfizm zrobił swoje. Zwykle nawet, być może. – tchrist

+0

@tchrist - bez sztuczki. Nigdy nie musiałem tego robić (jak zauważyłem w twoim komentarzu i odpowiedziach, nie jest to coś, co zwykle powinno się robić); tak, że gdy trzeba rozważyć "jak" powstały podczas odpowiadania [to] (http://stackoverflow.com/questions/10869511/is-there-a-way-to-know-the-methods-of-an-instance -of-an-unknown-class-in-perl/10869712 # 10869712), stanąłem przed koniecznością wybrania implementacji AN. A ja mocno wierzę w TIMTOWTDIBSWABTO. – DVK

Odpowiedz

8

Nie ma "standardowego sposobu", ponieważ nie jest to standardowa rzecz, którą chcesz zrobić. W przypadku czegokolwiek innego niż wizualizacja jest to czerwona flaga OO, która chce sprawdzić twoje drzewo dziedzictwa.

Oprócz Class :: ISA jest mro::get_linear_isa(). Oba są w rdzeniu przez jakiś czas, więc można je uznać za "standardowe" dla jakiejś definicji. Obaj pokazują spadek jako płaską listę, a nie drzewo, co jest przydatne głównie dla głębokiej magii.

perl5i meta object zapewnia zarówno linear_isa(), jak MRO (to właśnie nazywa MRO) oraz ISA() która zwraca klasę @ISA. Można go użyć do skonstruowania drzewa za pomocą prostej rekursji bez przechodzenia do tabel symboli.

use perl5i::2; 

func print_isa_tree($class, $depth) { 
    $depth ||= 0; 

    my $indent = " " x $depth; 
    say $indent, $class; 

    for my $super_class ($class->mc->ISA) { 
     print_isa_tree($super_class, $depth+1); 
    } 

    return; 
} 


my $Class = shift; 
$Class->require; 

print_isa_tree($Class); 

__END__ 
DBIx::Class 
    DBIx::Class::Componentised 
     Class::C3::Componentised 
    DBIx::Class::AccessorGroup 
     Class::Accessor::Grouped 
+0

"Na chwilę" - czy możesz to skwantyfikować? 5,12+? 5,8+? – DVK

+0

Nieważne. Too Lazy Dla Google. "Klasa :: ISA została wprowadzona do rdzenia Perla w wydaniu 5.8.0" (od ["Ukryte skarby w Perlu Core" @ perl.com] (http://www.perl.com/pub/2003/05/29 /treasures.html)); – DVK

+0

@DVK Zobacz także [corelist] (http://search.cpan.org/perldoc?corelist) – Schwern

1

Nie wierzę, że istnieje coś takiego jak "standardowy sposób CPAN". Badając @ISA jest powszechną praktyką - a także prawdopodobne, ponieważ techniki jak use base qw(...) i use parent -norequire, ... również działać na szczycie @ISA ...

+0

"standard" jak w "Użyj tekstu :: CSV {_XS}?" jest standardem do parsowania CSV. Tak, istnieją moduły do ​​analizy plików CSV, ale te lub 1-2 inne są najbardziej dojrzałe, używane przez zdecydowaną większość programistów itp. – DVK

+0

OK, punkt wzięty. Cóż, tak czy inaczej, rozważałbym przeanalizowanie '@ ISA' jako" standardu ". – mjhennig

4

myślę Class::ISA jest coś jak ty szukasz

use Class::ISA; 
use Mojolicious; 
print join "\n", Class::ISA::super_path("Mojolicious"); 

Drukuje:

Mojo 
Mojo::Base 

Jednak to nie jest jakaś "najlepsza praktyka", ponieważ całe zadanie nie jest czymś, co robią programiści Perla na co dzień.

0

Najprawdopodobniej te dni chcesz wykorzystać jedną z funkcji z mro, takich jak mro::get_linear_isa.

use mro; 
my @superclasses = mro::get_linear_isa($class); 
+0

typ zwrotu 'mro :: get_linear_isa' nie jest tablicą, ale arrayref !! – mikyra