Ich bekomme ::
immer wieder mit ->
beim Aufruf von Subroutinen aus Modulen. Ich weiß, dass ::
mehr auf Pfade bezogen ist und wo das Modul / Subroutine ist und ->
für Objekte verwendet wird, aber ich verstehe nicht wirklich, warum ich scheinbar beides vertauschen kann und es nicht zu sofortigen Fehlern kommt.
Ich habe Perl-Module, die Teil einer größeren Packung sind, z.B. FullProgram::Part1
Ich bin gerade dabei, Module in den Griff zu bekommen, bin aber immer noch auf wackligen Beinen, wenn es um Perl-Objekte geht, aber ich habe das versehentlich gemacht:
%Vor%statt
%Vor% Wenn ich also einen Hash-Ref an Subroutine1 übergeben habe und vorsichtig war, $class/$self
zu verwenden, um mit der Objektreferenz umzugehen und versehentlich ::
zu verwenden, dann ziehe ich mir die Haare aus und wundere mich, warum mein Hash-Ref verschwindet . Ich habe meine Lektion gelernt, möchte aber eine Erklärung für den Unterschied. Ich habe die Perldocs und verschiedene Webseiten gelesen, aber ich habe keine Vergleiche zwischen den beiden gesehen (ziemlich schwer zu googeln ...)
Alle Hilfe geschätzt - immer gut zu verstehen, was ich tue!
ruft die Unterroutine subroutine1
des Pakets FullProgram::Part1
mit einer leeren Parameterliste während
ruft die gleiche Subroutine mit dem Paketnamen als erstes Argument auf (beachten Sie, dass es beim Unterklassieren ein wenig komplexer wird). Diese Syntax wird von Konstruktormethoden verwendet, die den Klassennamen zum Erstellen von Objekten von Unterklassen wie
benötigen %Vor% Zu Ihrer Information: In Perl OO sehen Sie $object->method(@args)
, das Class::method
mit dem Objekt (eine gesegnete Referenz) als erstes Argument anstelle des Paket- / Klassennamens aufruft. In einer solchen Methode könnte das Unterprogramm wie folgt funktionieren:
ruft die Subroutine do_something_with
mit dem Objekt als erstes Argument auf, gefolgt von dem Wert von $bar
, das das zweite Listenelement war, das Sie ursprünglich an method
in @args
übergeben haben. Auf diese Weise geht das Objekt selbst nicht verloren.
Weitere Informationen darüber, wie der Vererbungsbaum beim Aufrufen von Methoden wichtig wird, finden Sie unter ikegamis Antwort !
Es gibt keinen inhärenten Unterschied zwischen einem Vanille-Sub und einem, das ist eine Methode. Es ist alles wie du es nennst.
%Vor% Dies ruft Class::foo
auf. Wenn Class::foo
nicht existiert, wird der Vererbungsbaum nicht geprüft. Class::foo
wird nur die angegebenen Argumente übergeben ( 'a'
).
Es ist ungefähr dasselbe wie: my $sub = \&Class::foo; $sub->('a');
Dies ruft Class::foo
oder foo
in einer seiner Basisklassen auf, wenn Class::foo
nicht existiert. Der Aufrufer (was links von ->
steht) wird als Argument übergeben.
Es ist ungefähr dasselbe wie: my $sub = Class->can('foo'); $sub->('Class', 'a');
Benutze beide!
%Vor%Beachten Sie, dass dies funktioniert, schützt Sie aber auch vor einer Mehrdeutigkeit dort; das einfache
%Vor%wird wie folgt interpretiert:
%Vor%(Aufruf der Subroutine Zwei in Modul und Versuch, class_method auf seinem Rückgabewert aufzurufen - was wahrscheinlich zu einem Laufzeitfehler oder Aufruf einer Klassen- oder Instanzmethode in einer komplett anderen Klasse führt) falls dort passiert Sei ein Sub Two in Modul - etwas, von dem du nicht abhängig sein solltest, denn es ist nichts von deinem Code, was in Module ist.
Historisch hatte Perl keine OO. Und funktioniert von Paketen, die mit FullProgram::Part1::subroutine1();
sytax aufgerufen werden. Oder sogar vorher mit FullProgram'Part1'subroutine1();
Syntax (veraltet).
Später haben sie OOP mit ->
sign implementiert, aber nicht wirklich zu viel geändert. FullProgram::Part1->subroutine1();
ruft subroutine1
und FullProgram::Part1
als 1. Parameter auf. Sie können diese Verwendung beim Erstellen eines Objekts sehen: my $cgi = CGI->new()
. Jetzt, wenn Sie eine Methode von diesem Objekt aufrufen, wird der linke Teil auch als erster Parameter zur Funktion: $cgi->param('')
. Das ist, wie param
das Objekt bekommt, von dem er aufgerufen hat (normalerweise mit dem Namen $self
). Das ist es. ->
ist Hack für OOP. Das hat zur Folge, dass Perl keine Klassen hat (Pakete funktionieren wie sie), aber auch Objekte ("Objekte" -Hacks - sie sind gesegnete Skalare).
Offtop: Sie können auch mit my $cgi = new CGI;
syntax aufrufen. Das ist dasselbe wie CGI->new
. Gleiches, wenn du print STDOUT "text\n";
sagst. Ja, einfach nur IOHandle::print()
aufrufen.