FLoH.tar hat geschrieben:
Ich habe das ganze doch mal kurz mit require getestet und weiß jetzt, dass ich mir damit zwar die ganzen Zeilen für den Code-Import via eval() sparen würde, dafür jedoch ALLE Variablen des Hauptprogramms globalisieren müsste, um aus dem importierten Code darauf zugreifen zu können, denn require basiert ja auf do FILE. Da our() aber alle Namensräume infiltriert, und ich nicht ausschließen kann, dass ich vielleicht doch ein Modul aus der Perl-Bib verwende, ist mir dies ein Gräuel.
FLoH.tar
Ne das stimmt so nicht ganz. Ein our() infilitriert nicht alle Namensräume und macht die Variable auch nicht überall Verfügbar. Eine globale Variable bei Perl bedeutet lediglich das diese variable egal wo du dich gerade befindest, immer von überall aufrufbar und veränderbar ist. Es bedeutet nicht das diese Variable in jeden namensraum existiert.
Denn Perl Header lasse ich mal weg, ich gehe davon aus das alle Skripte mit "use warnings" und "use strict" laufen.
our $string
Die variable $string an sich ist damit für die ganze Datei gültig. Das heißt wenn du in dieser Datei lediglich $string schreibst benutzt du diese "Globale" Variable. Es wird aber nur dann die Globale Variable genommen wenn es keine lexikalische Variable gibt, und auch nur dann wenn sich die our() Deklaration in der selben Datei befindet.
$string wird deswegen zu einer Globalen Variable, weil du mithilfe des package Namen also "$main::string" darauf zugriff hast. Es bedeutet nicht das $string jetzt innerhalb des package Net::FTP etc. existiert, dort ist die Variable völlig unbekannt. Du hättest aber aus dem Package Net::FTP über den Namen $main::string die Möglichkeit die Variable zu verändern. Das ist lediglich mit Global gemeint.
Ansonsten ist der Variablenname $string auch nur innerhlab der selben Datei gültig. Das ganze geht sogar soweit das es selbst für das selbe package gilt.
test.pl
our $string = "Hallo, Welt!\n";
main.plx
require "test.pl"
print $string;
Würde mit "use strict" in einem Kompilierfehler enden. Obwohl du sogar $string im selben package "main" angelegt hast, ist dieser Name in der Datei main.plx nicht verfügbar. Du kannst nur darauf zugreifen wenn du explizit den Globalen Namen benutzt. Sprich in main.plx dann "$main::string"
Global gültig bedeutet wie gesagt nur das es einen absoluten Namen gibt von dem du deine Variable immer verändern kannst. Das bedeutet aber nicht das die Variable deswegen sofort in jeder Datei vorhanden ist, weder noch im jeden package.
Wenn du es so siehst gibt es eigentlich gar keine richtigen Globalen Variablen in Perl.
Ansonsten solange du in main.plx auch keine neue our Deklaration machst, funktioniert dein Code auch normal weiter wie erwartet.
test.pl
our $string = "Hallo, Welt\n"
main.plx
require "test.pl"
my $string = "Leer\n";
print $string;
print $main::string;
Dieses würde dann folgendes ausgeben:
Leer
Hallo, Welt\n"
Weiterhin werden lixkalische Definitionen immer vor Gloabalen benutzt.
our $string = "Hallo, Welt!\n";
{
my $string = "foo\n";
print $string;
}
print $string;
Dies würde dann folgendes ausgeben:
foo
Hallo, Welt!
Möchtest du wie gesagt die globale und nicht die lexikalische Variable benutzen musst du den kompletten Namensraum angeben. In diesem fall also wieder "$main::string"
Ansonsten hat require aber noch eine eigenheit die sich von do() unterscheidet. Den es bindet jede Datei nur einmalig ein. Während do() die Datei immer wieder neu einbinden würde, was zu Problemen führen kann. Daher sollte man bei Bibliotheken schon require Benutzen. Oder bei richtigen OOP Bibliotheken natürlich "use" das dass require nochmals um paar Funktionen erweitert, und noch etwas mehr macht.
Ein weiteres Beispiel:
package foo;
our $string = "Hallo, Welt!\n";
package bar;
our $string = "Leer\n";
package main;
print $string;
print $foo::string;
print $bar::string;
Hier definierst du nicht eine Globale Variable, und diese Globale Variable wird auch nicht neu definiert. Du definierst zwei unterschiedliche Variablen.
1) $foo::string
2) $bar::string
Wenn du einfach nur "$string" schreibst, dann werden eigentlich erst lexikalische Variablen benutzt, und wenn es diese nicht gibt, die letzte Globale Definition in der aktuellen Datei, es würde als im ersten print "Leer" ausgegeben, wenn du das ganze wieder in Dateien aufteilst, geht das ganze wieder nicht. Von daher solltest du Globale Variablen auch immer mit dem kompletten Namen ansprechen, wenn du eine Globale Variable benutzen möchtest.
Ansonsten hat wie gesagt eine Globale Variable $foo::string keine Auswirkung auf dem Namesbereich Net::FTP etc. Von daher kannst du so viele Module benutzen wie du möchtest, ohne negative Auswirkungen. Es gibt halt an sich keine globalen Variablen. Global bedeutet bei Perl lediglich das du einen absoluten Namen besitzt von wo aus du immer direkt auf die Variable zugreifen kannst.
Und selbst wenn du hingehst und im Namensraum Net::FTP weitere globale Variablen definierst würde das keine Auswirkung auf die Methoden dort im package haben. Da lexikalische vor Globalen Variablen Namen genommen werden. Du würdest nur dann die Globale Variable nehmen wenn du sie, wie gesagt, explizit über den Kompletten Namen "$Net::FTP::variable" etc. anforderst.