Historia pytania:
OOP w Perl jest realizowane w oparciu o pakiety (package) i powiązanie referencji poprzez funkcję bless. Dziedziczenie osiągane jest dzięki tablicy @ISA, która automatycznie określa, w których pakietach Perl będzie szukać metod. Mechanizm wyszukiwania realizuje tzw. MRO (method resolution order).
Problem:
Chaotyczne zarządzanie tablicą @ISA i używanie SUPER bez zrozumienia porządku wyszukiwania metod często prowadzi do błędów, podwójnych wywołań lub niemożności nadpisania pożądanej funkcjonalności. Użycie AUTOLOAD wymaga kontroli, aby unikać pułapek nieskończonych pętli wyszukiwania.
Rozwiązanie:
Przykład kodu:
package Animal; sub speak { print "Animal speaks "; } package Dog; our @ISA = qw(Animal); sub speak { print "Dog barks! "; shift->SUPER::speak(); # wywołanie metody rodzica } my $dog = bless {}, 'Dog'; $dog->speak;
Kluczowe cechy:
Jeśli w łańcuchu dziedziczenia jest kilka rodziców z tymi samymi nazwami metod, która zostanie wywołana?
Wykonywane jest wyszukiwanie od lewej do prawej (zgodnie z kolejnością deklaracji w @ISA), wywoływana jest pierwsza znaleziona metoda.
Co się stanie, jeśli określona metoda nie występuje w całym drzewie dziedziczenia, a AUTOLOAD jest zrealizowany tylko w jednym z rodziców?
Perl wywoła AUTOLOAD tylko tej klasy, w której znajdzie go pierwszym w łańcuchu wyszukiwania metod. Pozostałe AUTOLOAD nie zadziałają, jeśli nie pojawią się wcześniej w @ISA.
Czy można zmienić porządek zwracania metody w locie?
Technicznie można zmieniać tablicę @ISA w czasie działania, ale prowadzi to do kruchości i trudnych do śledzenia błędów. Takie podejście zaleca się tylko w specyficznych przypadkach.
Użycie kilku klas rodzicielskich z tymi samymi nazwami metod, ich kolejność w @ISA nieprzewidywalnie zmienia się ręcznie, metody wywołują SUPER, co prowadzi do nieskończonej rekurencji.
Plusy:
Minusy:
Modyfikacje tylko poprzez jawne zadeklarowanie @ISA, a w razie potrzeby wielokrotnego dziedziczenia — wykorzystanie wyspecjalizowanych modułów typu mro::Concise lub Class::C3.
Plusy:
Minusy: