Thread Programmgerüst und Gültigkeitsbereiche
(20 answers)
Opened by tonewheel at 2007-04-13 12:24
Also die Variablenarten von Perl nämlich lexikalische Variablen und Package Variablen finde ich da doch etwas schwerer sie vernünftig zu erklären. Und reenes Beispiel fande ich auch eher ein schlechtes Beispiel ohne weitere Erklärung. Und wenn du reenees beispiel etwas abänderst:
Code: (dl
)
1 #!/usr/bin/perl Dann würde als Ausgabe nun sehr wohl "test" und "0.01" ausgegeben werden. Um es sogar kurz zu sagen hat eine lexikalische Variable überhaupt keine Auswirkung in welchem Package du dich befindest. In Reenees Beispiel wird überhaupt gar nix gekapselt. Es erscheint nur deswegen nicht 'Test' in der Ausgabe weil er auf eine Package Variable Namens $Test::test zugegriffen hat. Die hat er aber nie angelegt. Er hat eine lexikalische Variable angelegt. Er hätte genauso gut $Test::birne hinschreiben können. Wäre das selbe gewesen. Das ganze hat nichts mit Kapselung am Hut. ---------- 1) Es gibt zwei Arten von Variablen. Wie bereits gesagt existieren sogenannte Lexikalische Variablen und sogenannte Package Variablen. 2) Lexikalische Variablen haben ihren eigen Namesraum. Der Namensraum wird durch einen Block, oder wenn er nicht vorhanden maximal auf die Datei begrenzt 3) Package Variablen sind wie gesagt an Ihrem package gebunden. Sie sind letztendlich auch von überall aus zugreifbar und änderbar. 4) Um es nochmal Explizit zu sagen. Lexikalische Variablen sind "NICHT" an einem Package gebunden. Ob du eine lexikalische variable nun im Package A, B oder C deklarierst interessiert die lexikalische variable nicht. Sie wird lediglich durch einen Block oder die Datei begrenzt. Wenn du also eine lexikalische Variable deklarierst im package A und danach ins package Z wechselt hat es einen Effekt auf Package variablen, aber nicht auf die lexikalische. Bei dem wechseln hast du keinen Block oder die Datei ist zu ende. Es gilt also immer noch der selbe Gültigkeitsbereich für lexikalische Variablen 5) Wenn du Package Variablen mit "our" Deklarierst wird als Nebeneffekt noch zusätzlich eine lexikalische Variable erzeugt, die auf die Package variable zeigt. 6) Lexikalische Variablen werden immer vor Package Variablen genutzt. So hier mal Beispiele: Code: (dl
)
1 #!/usr/bin/perl Dieses Beispiel gibt "Hallo, Welt!\n" aus. Es wurde eine lexikalische Variable $string erzeugt. Wie bereits gesagt haben lexikalische Variablen Ihren eigenen gültigkeitsbereich, und sind an Blöcke oder die Datei begrent. Bei der Deklaration befand sich $string in keinem Block, ist also für die ganze Datei gültig. Das du nebenbei noch vorher und nachher das package änderst Interessiert die lexikalische Variable nicht die Bohne! Code: (dl
)
1 #!/usr/bin/perl Dieses Codeschnipsel funktioniert identisch zum Oberen und gibt wieder "Hallo, Welt!\n" aus. Es wurde zuersteinmal eine package variable in Test abgelegt: $Test::string und du wechselt danach nach main. Wenn du nun $string aufrufst passiert folgendes: Es wird zuerst geschaut ob eine lexikalische Variable vorhanden ist. Existiert keine dann wird versucht eine VAriable aus dem aktuellen package aufzurufen. Dies wäre dann eigentlich $main::string die es nicht gibt. Aber halt! Es existiert eine lexikalische Variable! Les dir nochmal Punkt 5 durch. Als Nebeneffekt wird durch "our" eine lexikalische Variable erzeugt die letztendlich ein Alias auf die aktuelle Package variable. Sprich es wird zeitglich dazu eine lexikalische Variable erzeugt die auf $Test::string zeigt. Und da Punkt 6 greift und lexikalische Variablen vor Package Variablen benutzt werden wird halt erfolgreich die Package Variable $Test::string ausgegeben. Code: (dl
)
1 #!/usr/bin/perl Was wird ausgegeben? Es wird "foo" ausgegeben. Als erstes erzeugst du zwar eine lexikalische Variable, aber diese wird durch den "our" Befehl überschrieben. Die lexikalische Variable zeigt nun auf $X::test anstatt den String "welt" zu enthalten. Da das ganze ein Nebeneffekt von our ist, bekommst du nichtmal eine Fehlermeldung angezeigt das du eine variable überschreibst! Danach wird wieder eine Package Variable in Y angelegt. Diese überschreibt wieder die lexikalische Variable und legt zuletzt ein Alias auf $Y::test an. Zuletzt gibst du $test aus. Das letzte was halt passiert ist war das $test eine Zuweisung nach $Y::test war. Also wird auch $Y::test ausgegeben. Wenn du die Variable aus dem Package X haben möchtest musst du dort nun den vollen Namen nutzen. "print $X::test;" Die Package Variablen an sich wurden ja nicht überschrieben, nur die lexikalische Variable immer wieder die ein Alias auf die Package Variable ist. Das einzige worauf du nie mehr zugreifen kannst ist die erste Deklaration. Den es wurde ja genau diese Variable immer wieder überschrieben. Um die Problematik zu umgehen kannst du bei mehreren Package Definition in einer Datei noch einen extra Block drum herum machen: Code: (dl
)
1 #!/usr/bin/perl Das wäre eine erfolgreiche Kapselung gewesen. Allerdiengs darf man sich wie gesagt nicht Irritieren lassen. $string ist nur deswegen nicht beim print zugreifbar weil die lexikalische Variable nur im Block Verfügbar ist. Die Package Deklaration hat damit überhaupt nichts zu tun. Oberes beispiel könntest du also auch so schreiben Code: (dl
)
1 #!/usr/bin/perl Es wird eine Variable $string angelegt, allerdiengs ist der Block danach schon sofort wieder zu ende, sprich die Variable wird danach sofort wieder Zerstört (eigentlich wird der Referenzcounter um 1 Reduziert und nur wenn er 0 ist wird die Variable Zerstört, aber das ist jetzt erstmal unwichtig. ;) ) So ich hoffe abschließend das ich dich jetzt vollständig verwirrt habe. ;) Wie gesagt man muss sich bewusst werden das es zwei Arten von Variablen gibt. Eigentlich ist das Konzeot dahinter nicht besonders schwer. Aber ich finde es am anfang doch recht verwirrend.\n\n <!--EDIT|sid burn|1176562484--> Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
|