Warum funktionieren '::' und '-' beim Austausch von Methoden aus Perl-Modulen synonym?

8

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!

    
dgBP 20.11.2012, 17:58
quelle

4 Antworten

7
%Vor%

ruft die Unterroutine subroutine1 des Pakets FullProgram::Part1 mit einer leeren Parameterliste während

auf %Vor%

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:

%Vor%

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 !

    
memowe 20.11.2012, 18:08
quelle
9

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');

%Vor%

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');

    
ikegami 20.11.2012 18:08
quelle
5

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.

    
ysth 20.11.2012 19:57
quelle
0

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.

    
PSIAlt 20.11.2012 18:18
quelle

Tags und Links