Warum sollte ich nicht UNIVERSAL::isa?
Gemäß dieser
http://perldoc.perl.org/UNIVERSAL.html
Ich soll nicht mit UNIVERSAL::isa() und sollte stattdessen mit $obj->isa() oder KLASSE->isa().
Dies bedeutet, dass, um herauszufinden, ob etwas eine Referenz in den ersten Platz, und dann ist die Referenz zu dieser Klasse zu tun haben, ich
eval { $poss->isa("Class") }
und check $@ und alle, die gumph, oder sonst
use Scalar::Util 'blessed';
blessed $ref && $ref->isa($class);
Meine Frage ist, warum? Was ist falsch mit UNIVERSAL::isa genannt, wie das? Es ist viel sauberer für Dinge wie:
my $self = shift if UNIVERSAL::isa($_[0], __PACKAGE__)
Sehen, ob diese Funktion für das Objekt aufgerufen wird oder nicht. Und ist es eine schöne, saubere alternative, die nicht umständlich mit kaufmännisches und potenziell lange Zeilen?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Das primäre problem ist, dass wenn Sie anrufen
UNIVERSAL::isa
direkt, Sie umgehen alle Klassen, überladen habenisa
. Wenn diese Klassen bauen auf den überlasteten Verhalten (was er vermutlich nicht, sonst würde Sie nicht überschrieben haben), dann ist das ein problem. Wenn man sich aufisa
direkt auf Ihrem gesegneten Objekt, dann die richtigeisa
- Methode aufgerufen werden in jedem Fall (überladen, wenn es vorhanden ist, UNIVERSELL:: wenn nicht).Das zweite problem ist, dass
UNIVERSAL::isa
nur dem test, den Sie möchten, auf eine gesegnete Referenz-genauso wie mit jeder anderen Nutzung derisa
. Es hat unterschiedliches Verhalten für nicht-gesegnet Verweise und einfache Skalare. Also dein Beispiel nicht überprüfen, ob$ref
ist wohl nicht das richtige zu tun, sind Sie zu ignorieren ist ein Fehler Zustand und mitUNIVERSAL
's Alternative Verhalten. Unter bestimmten Umständen kann dies zu subtilen Fehlern (zum Beispiel, wenn die variable enthält den Namen der Klasse).Betrachten:
So, in Zusammenfassung, verwenden Sie nicht
UNIVERSAL::isa
... Tun, die zusätzliche Fehler zu überprüfen, und rufen Sieisa
auf Ihr Objekt direkt.Siehe die Dokumentation für UNIVERSAL::isa und UNIVERSAL::can für, warum Sie sollten es nicht tun.
Kurz gesagt, ist es wichtig, die Module mit einem echten Bedarf überschreiben 'isa' (wie Test::MockObject), und wenn Sie es nennen, als eine Funktion, brechen Sie diese.
Muss ich sagen,
my $self = shift if UNIVERSAL::isa($_[0], __PACKAGE__)
sieht nicht sehr sauber für mich - anti-Perl-Befürworter würde sich beschweren, Linie Lärm. 🙂Direkt Ihre Frage zu beantworten, die Antwort ist an der Unterseite der Seite, die du verlinkt sind, nämlich, dass, wenn ein Paket definiert einen
isa
Methode aufrufenUNIVERSAL::isa
direkt nicht nennen werde das Paketisa
Methode. Das ist sehr unintuitiv Verhalten aus einem Objekt-Orientierung Sicht.Den rest von diesem post ist nur mehr Fragen, warum Sie dies tun in den ersten Platz.
In code wie den oben genannten, in welchen Fällen würden, dass bestimmte
isa
test scheitern? d.h., wenn es eine Methode, in dem Fall wäre das erste argument nicht das Paket, die Klasse oder eine Instanz davon?Ich Frage, weil ich Frage mich, ob es eine legitime Grund, warum Sie möchten, um zu testen, ob das erste argument ist ein Objekt, das in den ersten Platz. also, sind Sie nur versuchen zu fangen die Leute sagen
FooBar::method
stattFooBar->method
oder$foobar->method
? Ich glaube Perl ist nicht ausgelegt für diese Art von Verweichlichung, und wenn die Menschen irrtümlich mitFooBar::method
Sie werden es früh genug erfahren.Kann Ihre Laufleistung variieren.
Jeder andere hat gesagt, Sie warum, die Sie nicht verwenden möchten
UNIVERSAL::isa
, weil es bricht, wenn die Dinge überlastisa
. Wenn Sie gemacht haben alle die Gewohnheit, die überlastung, die sehr spezielle Methode, die Sie sicherlich wollen, Sie zu respektieren. Sicher, Sie könnte tun dies, indem Sie schreiben:weil
eval
garantiert false zurückgeben, wenn es eine Ausnahme auslöst, und der Letzte Wert sonst. Aber das sieht schrecklich, und Sie sollten nicht brauchen, um Ihren code schreiben, in lustige Möglichkeiten, weil die Sprache, die Sie zu will. Was wir wirklich wollen, ist, einfach zu schreiben:Das zu tun, müssten wir sicherstellen, dass
$foo
ist immer ein Objekt. Aber$foo
werden könnte, eine Zeichenfolge, eine Zahl, ein Verweis, eine Undefinierte Wert, oder alle möglichen seltsamen Sachen. Was für eine Schande, Perl kann nicht alles ein erste-Klasse-Objekt.Oh, warten Sie, es kann...
Können Sie packen autobox aus dem CPAN. Sie können es auch verwenden, mit lexikalischen Bereich, so kann alles sein, ein Erster-Klasse-Objekt nur für die Dateien oder Blöcke, in denen Sie verwenden möchten
->isa()
ohne all die zusätzlichen Kopfschmerzen. Es macht auch einen viel mehr als das, was ich abgedeckt haben in diesem einfachen Beispiel.eval { $foo->isa("thing") }
eher als ungewöhnlichautobox
- Modul, das auch auf die Leistung auswirkt.Vorausgesetzt, Ihr Beispiel, was Sie wollen in der Lage sein zu tun ist, innerhalb einer Objekt-Methode, Sie sind unnötig paranoid. Der erste übergebene Element wird immer entweder eine Referenz auf ein Objekt der entsprechenden Klasse (oder einer Unterklasse) oder es wird der name der Klasse (oder einer Unterklasse). Es wird nie einen Verweis von einer anderen Art, es sei denn, die Methode wurde bewusst als Funktion aufgerufen. Sie können daher sicher nur verwenden ref zu unterscheiden zwischen den beiden Fällen.
Recht. Es macht eine falsche Sache für Klassen, das überladen
isa
. Verwenden Sie einfach die folgende Redewendung:Ist es leicht verstanden und allgemein akzeptiert ist.