Operatory testów są pod tym względem wyjątkowe, bo przeładowujesz wszystkie albo żadne. Funkcja podpięta do operatora testu otrzymuje jako argumenty literę operatora (dla -e jest to e, dla -f jest to f) i wyrażenie z jego prawej strony.
Przykład:
#!/usr/bin/perl
use warnings;
BEGIN {
sub muminki {
return 2 + 2;
}
use overload(
'-' => sub {
my ($left, $right) = @_;
return 11;
},
'+' => \&muminki,
'-X' => sub {
#operator testów
my ($opType, $path) = @_;
print "Operator '$opType'. Argument: '$path'\n";
return;
}
);
}
if (-e '/tmp') {
print "Kaczka!\n";
} else {
print "Dziwaczka\n";
}
Ten przykład jest z jednej strony dobry, że operatory podawane są w stringach. Z drugiej strony ten sposób jest zależny od implementacji bardziej, niż np. *CORE::GLOBAL::open
. W końcu overload
to makro a nie słowo kluczowe. Efekt? Potrafi nie działać kompletnie nie wiadomo dlaczego.
Kolejna sprawa: moduły i klasy. Nie zawsze można przeładować operator w bieżącym pliku i trzeba zrobić to w module albo klasie. To kwestia kolejności ładowania funkcji. Chociażby funkcja printf
może być niedostępna w bloku BEGIN. O tym, że coś poszło w innej kolejności, niż spodziewa się użytkownik, można dowiedzieć się debugując kod.
Dla innych przykładów musiałbym pogrzebać na dysku a tego nie mam pod ręką. Ogólnie jest z tym sporo zabawy, żeby zadziałało jak należy. Sam nad tym siedziałem kawał czasu, więc nie ma co się dziwić, jeśli nie działa od razu :) . Tak, temat jest ciężki. To, że język udostępnia taką możliwość nie znaczy, że działa wszędzie tak samo.