Nehmen Sie ein einfacheres Beispiel
package Foo { sub new { die 7 } };
package Bar { sub new { die 42 } };
sub Foo { "Bar" }
Foo->new();
Im obigen Beispiel wird die Konstante Foo
in "Bar" aufgelöst, sodass dies "Bar"->new
nicht aufgerufen wird "Foo"->new
. Wie verhindern Sie die Auflösung des Unterprogramms? Sie können es zitieren.
"Foo"->new();
Was die Auswirkungen auf die Leistung betrifft, werden die Dinge nicht durch die Verwendung einer Zeichenfolge anstelle eines Barworts verschlimmert. Ich habe bestätigt, dass das von erzeugte Optree O=Deparse
dasselbe ist. In der Regel ist es daher besser, die Klassennamen zu zitieren, wenn Sie Wert auf Korrektheit legen.
Dies wird in Programming Perl erwähnt (leider im Zusammenhang mit dem indirekten Methodenaufruf ).
... also werden wir Ihnen sagen, dass Sie fast immer mit einem bloßen Klassennamen davonkommen können, vorausgesetzt, zwei Dinge sind wahr. Erstens gibt es keine Unterroutine mit demselben Namen wie die Klasse. (Wenn Sie der Konvention folgen, dass Unterprogrammnamen wie new
Start Kleinbuchstaben und Klassennamen wie ElvenRing
Start Großbuchstaben , ist dies nie ein Problem). Zweitens wurde die Klasse mit einem von geladen
use ElvenRing;
require ElvenRing;
Jede dieser Deklarationen stellt sicher, dass Perl weiß, dass ElvenRing
es sich um einen Modulnamen handelt, der erzwingt, dass jeder bloße Name wie new
vor dem Klassennamen ElvenRing
als Methodenaufruf interpretiert wird, selbst wenn Sie new
im aktuellen Paket zufällig eine eigene Unterroutine deklariert haben .
Und das macht Sinn: Die Verwirrung hier kann nur auftreten, wenn Ihre Unterprogramme (normalerweise Kleinbuchstaben) denselben Namen wie eine Klasse haben (normalerweise Großbuchstaben). Dies kann nur passieren, wenn Sie gegen die oben genannte Namenskonvention verstoßen.
tldr; Es ist wahrscheinlich eine gute Idee, Ihre Klassennamen zu zitieren, wenn Sie sie kennen und Wert auf Korrektheit legen.
Randnotiz: Alternativ können Sie die Auflösung eines Barworts zu einer Funktion stoppen, indem Sie ein ::
am Ende befestigen , z. B. oben Foo::->new
.
Vielen Dank an Ginnz auf reddit, der mich darauf hingewiesen hat , und an Toby Inkster für den Kommentar (obwohl es für mich beim ersten Lesen keinen Sinn ergab).
Foo::->new
wie ich von Ikegami gelernt habe.Foo::
hat den Vorteil, dass es warnt, wennFoo
es kein vorhandenes Paket gibtFoo->
ist zu erwarten, dass Sie in Ihrem Code mit wissen, dass Ihr Paket keine solche Unterroutine enthält. Aber wenn Sie Try :: Tiny und eine Reihe anderer cpan / anderer externer Module verwenden, wer sagt dann, ob eines von ihnen ein Try-Paket verwendet, und wenn ja, ob es ein Tiny-Sub enthält?Das explizite Zitieren des Klassennamens anstelle eines Barworts (das als Zeichenfolge behandelt wird) ist eine von drei Möglichkeiten, um syntaktische Mehrdeutigkeiten zu vermeiden. Der Abschnitt Aufrufen von Klassenmethoden in der perlobj-Dokumentation wird erläutert.
Sehen Sie diesen seltsamen Fall in Aktion mit der folgenden Demo.
Seine Ausgabe ist
Der Rest der oben genannten Dokumentation zeigt, wie Sie sich vor überraschendem Verhalten oder versehentlichen Fehlern schützen können.
Bei Beantwortung Ihrer Frage sind alle folgenden Anrufe gleichwertig.
Das Anhängen
::
an das Ende hat den Vorteil, dass eine hilfreiche Warnung ausgegeben wird. Angenommen, Sie haben versehentlich getipptDas produziert
quelle