Variable Scoping
Jede Variable ist nur verfügbar (und zugänglich) in dem Kontext, in dem sie deklariert wurde. Um den Kontext zu bestimmen, beziehen Sie sich auf die nächsten Öffnungs- und Schließmarken, die die Deklaration umgeben. Die meisten Programmiersprachen verwenden geschweifte Klammern ({}
), um den Anfang und das Ende eines Codeblocks zu markieren. Schauen Sie sich dieses Beispiel an:
Hier müssen Sie nicht jedes Stück Code verstehen. 🙂 Wenn wir über die Verfügbarkeit einer Variablen in einem Kontext sprechen, beziehen wir uns auf den Gültigkeitsbereich. Hier sehen Sie, dass die Variable root
zwischen den beiden lila umrandeten geschweiften Klammern deklariert wurde. Der Umfang dieser Variablen ist alles zwischen diesen beiden Klammern.
Der Gültigkeitsbereich einer Variablen kann sowohl lokal als auch global sein, je nachdem, wo eine Variable deklariert ist. Eine globale Variable kann für alle Klassen und Methoden innerhalb eines Programms verfügbar sein, während eine lokale Variable möglicherweise nur innerhalb der Methode verfügbar ist, in der sie deklariert ist:
Hier haben wir den Code um little und erweiterte unseren ersten Codeblock um einen weiteren! Wenn Sie die violetten Linien verfolgen, können Sie sehen, dass die Klammern aus dem ersten Block den gesamten Code aus dem zweiten Block umfassen. Als nächstes können Sie sehen, dass eine neue Variable, spy
, innerhalb des grünen lokalen Bereichs deklariert wurde.
Da die Variable root
im globalen Bereich deklariert wurde, bedeutet dies, dass auf alles innerhalb der violetten Klammern zugegriffen werden kann, einschließlich auf alles, was im lokalen Bereich deklariert ist. Im zweiten Codeblock sehen Sie eine Zeile direkt unter der Spy-Variablendeklaration, die root
. Das ist erlaubt!
Was sich jedoch im lokalen Bereich befindet, ist für den globalen Bereich oder andere lokale Codeblöcke nicht verfügbar. Schauen wir uns ein anderes Beispiel an:
Hier haben wir einen weiteren Codeblock hinzugefügt, der einen eigenen lokalen Bereich und eine eigene Variable hat, anotherSpy
. Schauen Sie sich nun die letzte Zeile in unserem Spy-Variablenblock an:
System.out.println(anotherSpy); // Error
Sieht so aus, als gäbe es einen Fehler! Das liegt daran, dass versucht wird, die Variable anotherSpy
zu verwenden. Dies ist jedoch nicht möglich, da anotherSpy
weder im globalen noch im lokalen Bereich liegt. Das bedeutet, dass dieser Codeblock nicht darauf zugreifen kann. anotherSpy
ist nur in dem Codeblock verfügbar, in dem es deklariert wurde.
Das gleiche gilt für die andere Richtung. Sie können sehen, dass die letzte Zeile unseres letzten Codeblocks ebenfalls einen Fehler aufweist:
System.out.println(spy); // Error
Hier wird versucht, die Variable spy aus einem anderen Codeblock zu verwenden. Dies ist jedoch nicht möglich, da sich spy
nicht im selben Bereich befindet wie der Codeblock, der versucht, ihn zu verwenden.
Variablenumfang in Klassen
Wenn Sie eine Klasse deklarieren, gelten die gleichen allgemeinen Regeln für den Gültigkeitsbereich: Auf jede Variable kann nur innerhalb ihres Deklarationsblocks zugegriffen werden. Experimentieren wir mit einer Unicorn-Klasse:
Genau wie in unserem ersten Beispiel gibt es sowohl globale als auch lokale Klassenvariablen. Lassen Sie uns im Detail überprüfen:
-
Die Variablen
height
undpower
sind Felder der Klasse und sind überall innerhalb der Klasse zugänglich. -
Auf die Variable
minutesToSleep
kann nur innerhalb des lokalen Bereichs des Codeblocks zugegriffen werden, in dem sie deklariert ist. -
Auf die Variable
minutesToRun
kann nur innerhalb des lokalen Bereichs des Codeblocks zugegriffen werden, in dem sie deklariert ist.
Der Gültigkeitsbereich einer Variablen schränkt ihre Zugänglichkeit per Definition ein. Klassenfelder sind jedoch außerhalb der Klasse zugänglich und können von jedem anderen Codeblock verwendet werden.
In unserem Beispiel sind das height
und power
. Wenn wir eine Klassenvariable deklarieren, können wir diese Werte lesen oder ändern:
Die Möglichkeit, mit Klassenvariablen herumzuspielen, kann schwerwiegende Folgen haben. Die gute Nachricht: Sie können das kontrollieren! Bevor wir herausfinden, wie, sollten Sie mit variablem Scoping üben.
Probieren Sie es selbst aus!
Zugriffskontrolle
Wir verwenden die Idee der Zugriffskontrolle, indem wir eingeschränkten Zugriff auf eine Klasse, ein Modul oder eine Datei implementieren. Sie wissen bereits, was eine Klasse und eine Datei sind, da wir mit ihnen gearbeitet haben!
Ein Modul ist ein Bündel verwandter Quelldateien, die einem Namen zugeordnet sind, wie ein Framework. Ein Framework ist eine Reihe von Funktionen, die nach einem bestimmten Kontext gruppiert sind. Es beschleunigt den Entwicklungsprozess und bietet Anleitungen zum Schreiben des Codes.
Es gibt eine Reihe von Frameworks, die von jeder Entwicklungsumgebung bereitgestellt werden. Tatsache ist, dass die Implementierung dieser Frameworks weit über das hinausgeht, was die Entwickler, die sie verwenden, sehen und nutzen können. Dies geschieht durch Einschränkung des Zugriffs auf die Details der Implementierung, auch bekannt als Implementierung der Zugriffskontrolle.
Kontrollebenen
In Java müssen Sie eines der Schlüsselwörter verwenden, um eine Kontrollebene festzulegen:
-
Public: sichtbar für die Welt und daher am wenigsten restriktiv
-
Protected: sichtbar für das Paket und alle seine Unterklassen
-
paketgeschützt: normalerweise nur für das Paket sichtbar, in dem sie sich befinden (Standardeinstellungen)
-
Privat: nur in dem Kontext zugänglich, in dem sie definiert sind (innerhalb der Klasse, in der sie sich befinden)
Die Implementierung dieser unterschiedlichen Einschränkungen erleichtert die Entwicklung erheblich. Sie müssen sich keine Gedanken über unerwünschte Sichtbarkeit Ihrer Implementierung und vor allem über unerwünschte Änderungen machen.
Setzen Sie ein geeignetes Schlüsselwort vor die zugehörige Deklaration:
Wenn Sie dann versuchen, von außerhalb der Klasse auf private Member zuzugreifen, erhalten Sie Fehler:
Die Kontrollstufen können sowohl Klassenelementen als auch Klassen zugewiesen werden:
public class PublicClass {}private class PrivateClass {}
Zusätzlich zur Sicherheit bietet die Angabe von Kontrollstufen für Klassenmitglieder eine bessere Lesbarkeit. Wenn ein Entwickler eine Quelldatei vorbereitet, ist immer klar, welche Elemente extern verwendet werden können.
Hierarchie der Kontrolle
Ein Element kann dieselbe oder eine restriktivere Kontrollstufe haben als sein enthaltendes Element:
Im obigen Beispiel wird die Klasse als public
deklariert . Da die Klasse das enthaltende Element ist, bedeutet dies, dass alle Elemente dieser Klasse das gleiche oder ein geringeres Expositionsniveau aufweisen können. In diesem Fall umfasst es alle Ebenen.
Wenn Sie eine Klasse als private
deklarieren, können ihre Elemente nur package-private
oder private
sein:
class PrivateClass { int internalProperty = 0; // automatically assigned package-private by default protected defaultProperty = true; // automatically assigned package-private public boolean publicProperty = true; // automatically converted to package-private private String fileprivateProperty = "Hello!"; //only available to the class private static void privateMethod() { }}
Im obigen Beispiel haben wir ein Attribut ohne explizites Schlüsselwort für die Zugriffskontrolle hinzugefügt. In diesem Szenario wird standardmäßig die Ebene des enthaltenden Elements angenommen. In diesem Fall ist es unsere Klasse, also nimmt sie das Niveau von PrivateClass
an.
Eine Klasse der obersten Ebene kann nicht als privat markiert werden, aber wenn Sie sie als Standard festlegen, wird sie in die paketgeschützte Ebene verschoben. Wenn beim Deklarieren einer Variablen einer Klasse die Steuerebene des Deklarationskontexts höher ist als die der Klasse, muss die Variable auch eine explizite Steuerebene haben. Deklarieren wir eine FileprivateClass Variable:
String a = PrivateClass(); // Errorprivate String b = PrivateClass(); // Okprivate String c = PrivateClass(); // Ok
Wie Sie sehen können, müssen Sie, wenn die Standardzugriffsebene des Variablenkontexts höher ist als eine Klasse, die Sie ihm zuweisen, die Ebene der Variablen explizit als gleich oder niedriger als die der Klasse angeben.
Zusammenfassung
In diesem Kapitel haben Sie etwas über die Zugänglichkeit von Variablen gelernt:
-
Ein Gültigkeitsbereich einer Variablen ist der Codebereich, in dem sie deklariert wurde.
-
Der allgemeine Variablenumfang gilt für alle Codeblöcke, einschließlich Klassen.
-
Eine weitere notwendige Möglichkeit, den Zugriff auf Variablen und Funktionen zu steuern, ist die Verwendung von Steuerungsebenen: public, protected, package-protected und private .