Thread Programmgerüst und Gültigkeitsbereiche (20 answers)
Opened by tonewheel at 2007-04-13 12:24

sid burn
 2007-04-16 16:56
#23683 #23683
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Quote
Das passt aber nicht zudem was du vorher gesagt hast:
Quote
5) Wenn du Package Variablen mit "our" Deklarierst wird als Nebeneffekt noch zusätzlich eine lexikalische Variable erzeugt, die auf die Package variable zeigt.

Was ja auch heißt, dass deren Wert überschrieben werden würde.

Jaein,
eigentlich wird der Wert nicht überschrieben. Da du in einem neuen Block bist, wird eine neue lexikalische Variable erzeugt. Da der Name zum Zugriff der selbe ist, verlierst du die Möglichkeit auf die vorherige zuzugreifen. Aber sie wird nicht überschrieben.

Das es nicht überschrieben wird kannst du an diesem Beispiel sehen.
Code: (dl )
1
2
3
4
5
6
#!/usr/bin/perl
use warnings;
use strict;

my $string = "Hallo";
{ my $string = "Welt"; }

Wenn die zweite Variable in dem Block die erste überschreiben könnte, dann würde hier eine Fehlermeldung kommen. Nämlich das $string bereits deklariert ist. Da du dich aber wie gesagt in einem neuen Block befindest gilt das als neuer Namensraum für lexikalische Variablen. Was dazu führt das eine komplett neue unabhängige lexikalische Variabel erzeugt wird. Wenn du die Klammern drum herum weg nimmst dann befindest du dich im selben namesraum wie die lexikalische Variable von davor. Dann würde es auch eine Fehlermeldung geben das du eine bereits definierte variable nochmal neu definierst.

Allerdiengs gibt es hier keinen Fehler. Den der Block stellt einen neuen Namensraum für lexikalische Variablen dar. Daher es wird im Block eine neue Variable $string erstellt. Es gibt nun zwei lexkialische Variablen die $string heißen, aber beide in einen anderen Namensraum.

Ansonsten wäre Temporär überschreiben folgendes:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
my $string = "Hallo, Welt!\n";
{
my $temp = $string;
$string = "wie geht es dir\n";

# tue etwas mit $string

# Variable wieder zurück setzen
$string = $temp;
}


Naja und ich sagte "Jaein" beim überschreiben, weil du dadurch halt kein Zugriff mehr auf die erste lexikalische Variable bekommst, dass ist natürlich richtig.

Allerdiengs gibt es ein Überschreiben von Variablen nur dann wenn du Package Variablen z.B: mit "local" nutzt. Dann wird die Original Variable wirklich überschrieben. Schau dir dazu mal folgende zwei Beispiel an.

Code: (dl )
1
2
3
4
5
6
7
8
9
my $string = "Hallo, Welt!\n";
sub print_out {
print $string;
}

{
my $string = "Wie geht es dir?\n";
print_out();
}


Code: (dl )
1
2
3
4
5
6
7
8
9
our $string = "Hallo, Welt!\n";
sub print_out {
print $string;
}

{
local $string = "Wie geht es dir?\n";
print_out();
}


Das erste Beispiel wird dir "Hallo, Welt!\n" ausgeben, dass zweite Beispiel jedoch "Wie geht es dir?\n".

Am Anfang wird eine lexikalische Variable definiert. Diese wird durch die darauffolgende Subroutine ausgegeben.

Danach beginnt ein neuer Block. Und es wird eine komplett neue lexikalische Variable definiert mit einem neuen String. Nun wird die Subroutine aufgerufen.

Die Subroutine hat aber einen komplett anderen Namensraum wie in unserem Block. Sie gibt also stattdessen die erste Variable aus. Die Zweite variable sieht die Subroutine gar nicht.

Das ist schon ein Beipsiel das die Variable nicht überschrieben wurde, sondern es zwei variablen gibt.


Im zweiten Beispiel wird die Variable wirklich überschrieben. Es wird eine Package Variable angelegt. Und die Subroutine soll diese Variable ausgeben.

Danach springen wir in den neuen Block. Das local bewirkt nun das die Package Variable "temporär" mit einem neuen Wert überschrieben wird. Die änderung an der Variable wird beim verlassen des Blockes wieder abgeändert.

Wenn wir allerdiengs innerhlab des Blockes die Subroutine aufrufen, dann gibt unsere Variable wirklich den neuen Wert aus. Denn es wurde die selbe variable genutzt, die temporär überschrieben wurde.

Quote
Macht man es in einem Block wird der Wert überschrieben, am Ende aber wieder zurückgesetzt, macht man es mit $Package::Variable wird der Wert nicht überschrieben.
Die lexikalische Variable wird vom Wert her also nicht verändert.
Anders als bei our().


Ich hoffe die Erklärung war oben gut genug.
In dem Block wird der Wert halt nicht überschrieben. Im Block ist ein neuer Namensraum für lexikalische variablen. Eine Deklaration mit "my" führt dazu das eine neue lexikalische Variable in diesem Namensraum erzeugt wird.

Trotzdem existiert die alte Variable weiterhin. Das einzige was du verlierst ist der Zugriff auf die lexikalische Variable von davor. Da immer die "engere" lexikalische Variable benutzt wird.

Bei "our" ist es das gleiche. Wenn du ein Block noch zusätzlich um dein ganzes Package + Methoden etc. machst bildest du damit auch gleichzeitig einen neuen Lexikalischen Raum. Ein our erstellt also noch zusätzlich eine neue lexikalische Variablen innerhalb dieses Blockes.


Die Definition über den vollen Package Namen würde ich halt deswegen nicht machen:
1) Wenn sich der Package Name ändert musst du alle Variablen abändern.
2) Wenn du eine lexikalische Variable nur in einem Package haben möchtest, dann solltest du einen Block drum herum machen und auch nur dort die lexikalische Variable erzeugen. Und nicht ausserhalb des Blockes.
3)Variablennamen solltest du dann so wählen das dort eben keine überscheidung zustande kommt.
4) Eine lexikalische Variable ausserhalb des Blockes zu definieren würde nur Sinn machen wenn du die variable mit mehreren Packages Teilen möchtest. Aber zum einen sollten sowieso nicht mehrere Packages in einer Datei liegen. Damit gibt es dann auch keine Probleme mit lexikalischen variablen die über mehrere Packages hinweg gelten. Möchtest du halt wirklich das eine variable über mehrere Packages gültig ist, dann solltest du dafür auch eine Package Variable nutzen.

Ich sehe also kein Problem darin "our" zu nutzen. Den über Variablen die für mehrere Packages gültig ist, solltest du Package variablen nutzen. Und alle lexikalischen Variablen die du benötigst solltest du innerhalb des Blockes definieren wo du auch das package definierst.

Ich hoffe meine Argumentation ist Verständlich genug. ^^\n\n

<!--EDIT|sid burn|1176728877-->
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de

View full thread Programmgerüst und Gültigkeitsbereiche