Geschiedenis van de kwestie:
Operator overload (overloading) en het gebruik van magische methoden is een van de geavanceerde aspecten van Perl, cruciaal voor het creëren van eigen objectabstraheringen, complexe types die wiskunde, vergelijkingen en conversies naar string ondersteunen. Perl was van oorsprong niet gericht op OOP en overloading, maar vanaf versie 5 werd het mogelijk om het standaardgedrag van objecten uit te breiden via pragma overload en het aansluiten van speciale methoden.
Probleem:
De sleutel tot deze subtiliteit is dat het mechanisme zeer flexibel is, maar het is gemakkelijk om fouten te maken: het gedrag van de overbelaste objecten is niet altijd intuïtief, onjuiste overloads leiden tot eindeloze recursie, ongewenste casts en contextfouten. Het grootste deel van de fouten komt voort uit het mengen van string- en numerieke overloads, evenals onverwachte verwijzingen naar niet-beschreven operator methoden.
Oplossing:
Gebruik strikt de pragma overload voor de benodigde operators, beschrijf duidelijk de manieren om het object om te zetten, anticipeer op het werk in beide contexten (numeriek en string) en beschrijf expliciet de fallbacks. Het wordt aangeraden om alle verwachte operators af te handelen en zorgvuldig om te gaan met de overloading van erfelijkheden.
Codevoorbeeld:
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; # Gebruik my $a = MyNum->new(5); my $b = MyNum->new(7); my $c = $a + $b; print "$c "; # 12
Belangrijke kenmerken:
Misleidende vraag 1: Zal bij alleen het overbelasten van stringcontext operators (""") de numerieke vergelijking automatisch werken?
Nee, het numerieke omzetten (0+) moet expliciet worden beschreven, anders zal Perl proberen om het via de stringmethode te zetten, wat niet altijd leidt tot het verwachte resultaat (bijvoorbeeld, voor eq/== is er verschillend gedrag).
Misleidende vraag 2: Zal het overbelaste object operators ondersteunen die niet expliciet in pragma overload zijn vermeld?
Nee, alleen degene die expliciet zijn vermeld. De rest gebruikt het basisgedrag of leidt tot fouten.
Misleidende vraag 3: Kan een overbelaste operator een eenvoudige scalair in plaats van een object retourneren?
Ja, maar het verliest de keten van methoden en objectiviteit, wat leidt tot fouten in de latere code: of de overload voor volgende operaties stopt met werken, of de logica zal breken.
De ontwikkelaar heeft alleen de operator "+" en "" voor zijn object overbelast, terwijl hij 0+, -, cmp is vergeten. Bij vergelijking via "==" kreeg hij een onjuist resultaat, omdat stringification werkte en niet de juiste omzetting.
Voordelen:
Nadelen:
De ontwikkelaar gebruikt pragma overload en bestrijkt alle noodzakelijke operators (", 0+, +, -, x, <=>), en gooit een uitzondering voor incompatibele gevallen met een informatieve foutmelding.
Voordelen:
Nadelen: