2012-06-13 17 views
5

Nie mogę znaleźć wyjaśnienia, jak polimorfizm działa w Perlu. Rozumiem, co oznacza polimorfizm, ale staram się dowiedzieć, jak to działa wewnętrznie w Perlu. Czy ktoś może wskazać mi jakąś dokumentację, która to wyjaśnia. Wszystkie wyszukiwania w Google, które zrobiłem daje mi przykłady tego, co polimorfizm jest w perlu, ale nie w jaki sposób perl sprawia, że ​​działa.Jak działa polimorfizm Perla?

+0

Wewnętrzna implementacja czy składnia/użycie? – djechlin

Odpowiedz

14

Po wywołaniu obiektu lub klasy, Perl sprawdza, czy ta metoda jest dostarczana bezpośrednio przez samą klasę.

Ponieważ classes are simply Perl packages, jest to po prostu kwestia sprawdzenia istnienia podprogramu &Class::method.

Jeżeli taki podprogram zostanie znaleziony, Perl bada tablicę @ISA w tym samym opakowaniu (tj @Class::ISA), który zawiera listę klas bazowych dla klasy, i robi to samo sprawdzanie każdego pakietu/klasy, który pojawia się w środku.

Każda z tych klas z kolei może mieć również tablicę @ISA, więc wyszukiwanie jest rekurencyjne.

Na koniec, jeśli metoda nie zostanie znaleziona w tej metodzie, Perl wyszuka w specjalnym pakiecie UNIVERSAL dla podprogramu &UNIVERSAL::method.

Niepowodzenie w tym momencie pociąga za sobą system AUTOLOAD, ale to naprawdę wykracza poza zasadę polimorfizmu.

Niepowodzenie znalezienia odpowiedniej metody dopasowywania w dowolnym miejscu powoduje wyjątek.

0

To dobrze pasuje do polimorfizmu opartego na dziedziczeniu i daje pewne pojęcie o tym, co konkretnie robi Perl. Zawsze stosowałem rozdział 12.5. Dziedziczenie klas w Programming Perl jako odniesienie dla tych rzeczy.

+0

dla Perl OOP, zawsze lubiłem "Learning Perl Objects, References and Modules" od O'Reilly: http://shop.oreilly.com/product/9780596004781.do – David

7

Rozdział 7 od Object Oriented Perl, Damian Conway, Manning (2000) nazywa się Polimorfizm. Dziesięć stron.

Należy jednak pamiętać, że w przypadku języka C++ lub Java lub C# lub podobnego, nie ma zbyt wiele informacji o "polimorfizmie" w języku Perl. Powiedziałbym nawet, że koncepcja polimorfizmu sprawia, że ​​rzeczy są bardziej skomplikowane niż w Perlu.

Myślę, że mechanizmem, który powinien starać się zrozumieć programista Perl, jest sposób działania metody. Odpowiedź brzmi: pierwsze skanowanie w trybie rekursywnym z głębokościami poprzez macierze paczek o numerach @ISA.

Przykład, zróbmy $o->bla. Nasz $o jest dostępny w pakiecie A, który nie ma implementacji bla. Ale dziedziczy po pierwszym B, a następnie C (@ISA = ('B', 'C')). Zróbmy najpierw odnośnik w B. Nie definiuje również metody. Gdyby miał klasy rodziców, kontynuowalibyśmy nasze poszukiwania. Ale tak nie jest. Tak więc teraz patrzymy na C i na szczęście ma ona metodę, inaczej byłby to błąd wykonania, ponieważ pakiet ostatniej instancji, UNIVERSAL, również nie definiuje bla.

4

Obiekt metoda połączenia jest w zasadzie zoptymalizowane * wersja z następujących czynności:

my $class = ref($_[0]); 
my @isa = mro::get_linear_isa($class); 
for my $pkg (@isa) { 
    if (exists(&{$pkg.'::'.$method_name})) { 
     return &{$pkg.'::'.$method_name}; 
    } 
} 

ref pobiera nazwę klasy związanego z obiektem. Klasa jest przechowywana w zmiennej obiektu.

$ perl -MDevel::Peek -e'my $o = {}; Dump($o); bless($o, "SomeClass"); Dump($o);' 
SV = IV(0x9e4ae0c) at 0x9e4ae10 
    REFCNT = 1 
    FLAGS = (PADMY,ROK) 
    RV = 0x9e317d0 
    SV = PVHV(0x9e36808) at 0x9e317d0 
    REFCNT = 1 
    FLAGS = (SHAREKEYS) 
    ARRAY = 0x0 
    KEYS = 0 
    FILL = 0 
    MAX = 7 
    RITER = -1 
    EITER = 0x0 
SV = IV(0x9e4ae0c) at 0x9e4ae10 
    REFCNT = 1 
    FLAGS = (PADMY,ROK) 
    RV = 0x9e317d0 
    SV = PVHV(0x9e36808) at 0x9e317d0 
    REFCNT = 1 
    FLAGS = (OBJECT,SHAREKEYS)  <---- 
    STASH = 0x9e323d0 "SomeClass" <---- 
    ARRAY = 0x0 
    KEYS = 0 
    FILL = 0 
    MAX = 7 
    RITER = -1 
    EITER = 0x0 

get_linear_isa opiera się na @ISA w pakiecie $class i @ISA pakietów w nim wymienione.

Ponieważ nazwa klasy znajduje się w obiekcie, a Perl może sprawdzać tablicę symboli w czasie wykonywania, wirtualna tabela metod nie jest potrzebna do zapewnienia polimorfizmu.

* — Buforuje to, który pakiet udostępnia metodę $ nazwa_metody dla klasy klasa. Co więcej, z pewnością nie oblicza całego liniowego ISA z góry, ale w razie potrzeby.

1

Polimorfizm jest po prostu pomysłem, że obiekty różnych typów odpowiadają na wywołania metod o tej samej nazwie. Słabo napisane języki, takie jak Perl, są "niejawnie polimorficzne".

Przykładowo CGI przedmiot, przedmiot Apache2::Request i Plack::Request obiektu mają sposób param które powrotu parametry żądania HTTP. Mógłbym napisać funkcję, która akceptuje obiekt jako parametr, i wywołać metodę param na tym obiekcie i uzyskać parametr żądania HTTP, nie wiedząc, jaki typ obiektu jest.

Języki mocno napisane nie działają w ten sposób, ponieważ ich funkcje określają typy danych swoich parametrów. Nie mogę wywołać funkcji w Javie z obiektem typu Dog, jeśli oczekiwał on jednego z Cat. Tak więc silnie typowane języki muszą tworzyć specjalne mechanizmy pozwalające na polimorfizm.