Historie der Frage:
Die Operatorüberladung (Overloading) und die Verwendung magischer Methoden sind eine der fortgeschrittenen Seiten von Perl, die lebenswichtig für die Erstellung eigener objektbezogener Abstraktionen ist, komplexer Typen, die arithmetische Operationen, Vergleiche und String-Konvertierungen unterstützen. Perl war ursprünglich nicht auf OOP und Overloading ausgerichtet, aber seit Version 5 ist es möglich, das Standardverhalten von Objekten durch die pragma overload und das Hinzufügen von Spezialmethoden zu erweitern.
Problem:
Der Schlüsselpunkt ist, dass der Mechanismus sehr flexibel ist, aber leicht Fehler entstehen können: Das Verhalten eines überladenen Objekts ist nicht immer intuitiv, inkorrekte Überladungen führen zu endloser Rekursion, unerwünschten Typumwandlungen und Kontextfehlern. Der Großteil der Fehler entsteht durch die Vermischung von string- und nummerischen Überladungen sowie durch unerwartete Zugriffe auf nicht definierte operatorische Methoden.
Lösung:
Verwenden Sie strikt die pragma overload für die benötigten Operatoren, beschreiben Sie klar die Methoden zur Umwandlung des Objekts, antizipieren Sie das Arbeiten in beiden Kontexten (numerisch und string) und beschreiben Sie ausdrücklich die Fallbacks. Es ist ratsam, alle erwarteten Operatoren zu bearbeiten und auf die Vererbung von Überladungen zu achten.
Beispielcode:
package MyNum; use overload '+' => 'add', '""' => 'as_string'; sub new { my ($class, $value) = @_; bless { val => $value }, $class; } sub add { my ($self, $other, $swap) = @_; my $sum = $self->{val} + (ref($other) ? $other->{val} : $other); return __PACKAGE__->new($sum); } sub as_string { my $self = shift; return $self->{val}; } 1; # Verwendung my $a = MyNum->new(5); my $b = MyNum->new(7); my $c = $a + $b; print "$c "; # 12
Schlüsselfeatures:
Fangfrage 1: Wenn nur die String-Überladung der Operatoren (""") erfolgt, wird dann der numerische Vergleich automatisch funktionieren?
Nein, die numerische Umwandlung (0+) muss ausdrücklich beschrieben werden, andernfalls wird Perl versuchen, über die String-Methode umzuwandeln, was nicht immer zu den erwarteten Ergebnissen führt (zum Beispiel unterschiedliche Verhaltensweisen bei eq/==).
Fangfrage 2: Unterstützt ein überladenes Objekt Operatoren, die nicht ausdrücklich in pragma overload aufgeführt sind?
Nein, nur die, die ausdrücklich aufgelistet sind. Alle anderen verwenden das grundlegende Verhalten oder führen zu Fehlern.
Fangfrage 3: Kann ein überladener Operator einen einfachen Skalar anstelle eines Objekts zurückgeben?
Ja, kann er, aber es verliert die Methodenverkettung und Objektivität, was zu Fehlern in weiterem Code führt: entweder die Überladung für nachfolgende Operationen funktioniert nicht mehr, oder die Logik wird beschädigt.
Ein Entwickler hat nur die Operatoren "+" und "" für sein Objekt überladen und die 0+, -, cmp vergessen. Bei einem Vergleich durch "==" erhielt er ein inkorrektes Ergebnis, weil die Stringifizierung wirksam wurde, und nicht die benötigte Umwandlung.
Vorteile:
Nachteile:
Ein Entwickler verwendet pragma overload und deckt alle benötigten Operatoren (", 0+, +, -, x, <=>) ab, und für inkompatible wirft er eine Ausnahme mit einer informativen Fehlermeldung.
Vorteile:
Nachteile: