Module und Packages
Hier ein kleines Beispiel, um ein Problem deutlich zu machen: Wir haben ein Modul geschrieben, in dem die Funktion myPrint definiert ist. Dieses Modul binden wir ein, weil wir irgendetwas davon brauchen. Im Hauptprogramm selbst haben wir erneut eine Funktion erstellt mit dem gleichen Namen. Das Problem ist jetzt klar: Es gibt zwei verschiedene Funktionen mit dem gleichen Namen und das ist nicht so gut ...
Packages
Die Lösung für dieses Problem: Es ist unter Perl möglich Namensräume, sogenannte Packages, zu definieren. Das hat zum Vorteil, dass man in verschiedenen Namensräumen denselben Variablen- oder Funktionsnamen gebrauchen kann. Wird kein Namensraum bez. Package angegeben, dann befindet man sich im Default-Package main. Das bedeutet, dass man, wenn man keinen Namensraum angibt - was wir bis jetzt auch gemacht haben - stets mit diesem Dafault-Package gearbeitet haben.
&bla();
&xyz::bla();
sub bla { print "bla\n"; }
package xyz;
print "\npackage xyz\n\n";
sub bla { print "xyzbla\n"; }
&bla();
&main::bla();
&::bla();
package main;
print "\npackage main\n\n";
&bla();
&xyz::bla();
package abc;
print "\npackage abc\n\n";
&::bla();
&main::bla();
&xyz::bla();
bla
xyzbla
package xyz
xyzbla
bla
bla
package main
bla
xyzbla
package abc
bla
bla
xyzbla
Und das fällt auf:
- Ein File befindet sich standardmäßig im Package main.
- Der Namensraum wird mit package NAME; eingeleitet und reicht bis zum nächsten Namensraum bzw. Ende des Files.
- Will man eine Funktion ansprechen, die in einen anderen Namensraum liegt, so muss man den Namensraum zuvor angeben. Danach stehen zwei Doppelpunkte (::) und dann der Funktionsname. Wichtig dabei die Kennzeichnung, dass eine Funktion vorliegt - also das & - steht vor dem Namensraum. Skalare Variablen, Hashes, etc. spricht man analog an. Auch hier muss die Kennzeichnung ($, @, ...) vor dem Namensraum stehen. Das gilt aber nur für Variablen und Funktionen, die nicht mit my deklariert sind.
- Gleichnamige Funktionen, Variablen, etc. in verschiedenen Namensräumen machen keine Probleme.
- Man kann innerhalb eines Files den Namensraum ändern
- und wieder zu einem verlassenen Namensraum zurückkehren (das ist aber nicht sehr übersichtlich).
Ein weiteres Beispiel mit einem Modul myMath.pm und einem File, das dieses Modul einbindet:
Das File myMath.pm enthält folgenden Code:
package myMath;
$PI=3.14159265358979323846;
sub plus { $_[0]+$_[1]; }
sub minus { $_[0]-$_[1]; }
sub times { $_[0]*$_[1]; }
sub over { $_[0]/$_[1]; }
1;
use myMath;
print &myMath::plus(3,5)."\n";
print &myMath::minus(3,1)."\n\n";
print $myMath::PI;
8
2
3.14159265358979
@EXPORT, @EXPORT_OK und qw
Nun ist es möglich, dass Module wiederum Module einbinden können. Darunter leidet vor allem die Übersichtlichkeit eines Moduls. Deshalb wurde eine Möglichkeit geschaffen, die einem Modul erlaubt, den Programmierer dazu zu zwingen, die Funktionen und Variablen (auch Symbole genannt), die er einbinden will, anzugeben.
Dieses "Erzwingen" wird mit Hilfe des Moduls Exporter.pm erreicht. Es erwartet im eingebundenen Modul zwei Arrays: @EXPORTER und @EXPORTER_OK. Das erste Array beinhaltet (oder soll beinhalten) die Funktions- und Variablennamen (Symbole), die standardmäßig exportiert werden, also vom einbindenden Modul importiert werden. @EXPORTER_OK hingegen enthält die Namen, die maximal exportiert werden können (aber nicht müssen), also vom einbindenden Modul importiert werden können.
Hier das obige Beispiel - etwas professioneller:
package myMath;
use Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(&plus &minus × &over);
@EXPORT_OK = qw($PI);
$PI=3.14159265358979323846;
sub plus { $_[0]+$_[1]; }
sub minus { $_[0]-$_[1]; }
sub times { $_[0]*$_[1]; }
sub over { $_[0]/$_[1]; }
1;
use myMath;
print &plus(3,5)."\n";
print &minus(3,1)."\n\n";
print $myMath::PI;
8
2
3.14159265358979
use myMath qw(&plus &minus $PI);
print &plus(3,5)."\n";
print &minus(3,1)."\n\n";
print $PI;
8
2
3.14159265358979
Erklärung:
- Als erstes wird in myMath.pm ein Namensraum angegeben (package maMath;) - wie gehabt - und
- das Exporter-Modul eingebunden.
- Mit @ISA = qw(Exporter); wird die import-Funktion aus dem Exporter-Modul (bzw. Klasse) dem aktuellen Modul zugefügt (genauer gesagt vererbt). Man braucht diese Zeile eben ...
- Die qw()-Funktion erleichtert dem Programmierer nur Schreibarbeit und trägt - so meinen einige - der Übersichlichkeit bei. qw(Exporter) entspricht nämlich ('Exporter') und qw(&plus &minus $PI) entspricht ('&plus', '&minus', '$PI').
- Mit @EXPORT = qw(&plus &minus × &over); werden die Funktionen plus, etc. in das Standardexportarray geschrieben, was im Programm m1.pl ausgelesen wird.
- In m2.pl wird nicht aus @EXPORTER importiert, sondern aus @EXPORTER_OK, da explizit die einzubindenden Symbole nach dem use myMath angegeben werden. Die Funktionen × und &over wurden in m2.pl nicht mit eingebunden!