Sichtbarkeit (Programmierung)

Die Sichtbarkeit gibt in der strukturierten und objektorientierten Programmierung an, in welchen Programmteilen die Bezeichnern von Datentypen, Variablen, Funktionen oder Konstanten sowie Prozeduren oder Methoden verwendet werden können, die in einer bestimmten Programmeinheit wie zum Beispiel einer Klasse oder einem Modul definiert wurden.[1]

Die Sichtbarkeitsregeln werden in den dazugehörigen Schnittstellen mit Hilfe von Zugriffsmodifikatoren festgelegt.[2] Die übliche Einteilung ist:[3]

  • öffentlich (Modifikator "public"), auf das Element darf von jeder anderen Klasse aus zugegriffen werden.
  • geschützt (Modifikator "protected"), auf das Element darf (üblicherweise) nur von derselben oder erweiternden Klassen aus zugegriffen werden.[4]
  • privat (Modifikator "private"), auf das Element darf nur innerhalb des definierenden Bereiches zugegriffen werden.

Um die Möglichkeit von versehentlichen Verwechslungen und Programmierfehlern zu begrenzen, empfiehlt es sich die Sichtbarkeiten von Bezeichnern so weit wie möglich einzuschränken (Abschattung).[2] In strukturierten Programmiersprachen beschränkt sich die Sichtbarkeit der Parameter und lokalen Variablen von Prozeduren, Funktionen und Methoden auf diese selbst.[5] Innerhalb des Sichtbarkeitsbereichs können Datentypen oder Prozeduren rekursiv referenziert werden.[5] Globale Variablen sind in der gesamten entsprechenden Programmeinheit (zum Beispiel in einem Programmpaket, in einem Modul oder in einer Klasse) sichtbar.

Viele Programmierer verwenden zur Erleichterung der Unterscheidbarkeit im Quelltext für lokale Variablen und für globale Variablen verschiedene Namenskonventionen, beispielsweise für lokale Variablen Bezeichner, die mit einem Kleinbuchstaben beginnen, und für globale Variablen Bezeichner, die mit einem Großbuchstaben beginnen.[6]

Definition

Bei den meisten Programmiersprachen gibt es drei Orte, an denen Variablen deklariert werden können:

  • In einer Funktion oder einem Block. Solche Variablen werden als lokale Variablen bezeichnet. Sie können nur innerhalb der Funktion oder dem Block verwendet werden.
  • Außerhalb aller Funktionen. Solche Variablen werden als globale Variablen bezeichnet. Sie können in allen Funktionen und Blöcken verwendet werden.
  • In der Definition von Funktionsparametern. Solche Variablen werden als formale Parameter bezeichnet. Sie können nur innerhalb der Funktion verwendet werden.

Variablen in C

Die folgenden Beispiele verwenden die Programmiersprache C.[7]

Variablen, die in einer Funktion oder einem Block deklariert sind, werden als lokale Variablen bezeichnet. Sie können nur von Anweisungen verwendet werden, die sich in dieser Funktion oder dem Block befinden. Das folgende Beispiel zeigt, wie lokale Variablen verwendet werden.

#include <stdio.h>

// Hauptfunktion
int main()
{
	// Deklaration der lokalen Variablen
	int a, b, c;

	// Initialisierung der lokalen Variablen
	a = 100001;
	b = 11;
	c = a / b; // Weist das Ergebnis der Division der Variablen c zu

	// Ausgabe auf der Konsole
	printf("Die Division lautet: %d / %d = %d\n", a, b, c);
}

Globale Variablen werden außerhalb einer Funktion definiert, und zwar in der Regel am Anfang des Programms. Globale Variablen behalten ihre Werte während der gesamten Laufzeit des Programms und können in einem der für das Programm definierten Funktionen aufgerufen werden. Auf eine globale Variable kann von jeder Funktion aufgerufen werden. Das heißt, eine globale Variable steht nach seiner Deklaration im gesamten Programm zur Verfügung. Das folgende Programm zeigt, wie globale Variablen verwendet werden.

#include <stdio.h>

// Deklaration der globalen Variable
int d;

// Hauptfunktion
int main()
{
	// Deklaration der lokalen Variablen
	int a, b;

	// Initialisierung der lokalen Variablen
	a = 100001;
	b = 9091;
	d = a / b; // Weist das Ergebnis der Division der globalen Variable d zu

	// Ausgabe auf der Konsole
	printf("Die Division lautet: %d / %d = %d\n", a, b, d);
}

Formale Parameter werden als lokale Variablen in einer Funktion behandelt und haben Vorrang vor globalen Variablen, wie folgendes Beispiel zeigt.

#include <stdio.h>

// Deklaration der globalen Variable
int b = 100001;

// Funktion, die den Quotienten von zwei ganzen Zahlen berechnet
int quotient(int a, int b)
{
	// Ausgabe auf der Konsole
	printf("Wert von a in der aufgerufenen Funktion: %d\n", a); // Gibt den formalen Parameter a aus
	printf("Wert von b in der aufgerufenen Funktion: %d\n", b); // Gibt den formalen Parameter b aus
	return a / b; // Gibt das Ergebnis der Division als Rückgabewert der Funktion zurück
}

// Hauptfunktion
int main()
{
	// Deklaration und Initialisierung der lokalen Variablen in der Hauptfunktion
	int a = 11;
	int c;

	// Ausgabe auf der Konsole
	printf("Wert von a in der Hauptfunktion: %d\n", a); // Gibt die lokale Variable a aus
	printf("Wert von b in der Hauptfunktion: %d\n", b); // Gibt die globale Variable b aus
	c = quotient(b, a); // Aufruf der Funktion, die den Quotienten berechnet
	printf("Wert von c in der Hauptfunktion: %d\n", c); // Gibt die lokale Variable c aus
}

Blöcke

In vielen, aber nicht allen blockstrukturierten Programmiersprachen kann der Gültigkeitsbereich auf einen Block beschränkt werden, der als Blockbereich bezeichnet wird. Meistens ist dieser Block in einer Funktion enthalten, wodurch der Bereich auf einen Teil einer Funktion beschränkt wird.

Ein repräsentatives Beispiel für die Verwendung des Blockbereichs ist der hier gezeigte Code in der Programmiersprache C, bei dem zwei Variablen auf die Schleife angewendet werden: die Schleifenvariable n, die einmal initialisiert und bei jeder Iteration der Schleife inkrementiert wird, und die Hilfsvariable n_squared, die wird bei jeder Iteration initialisiert.

unsigned int sum_of_squares(const unsigned int N)
{
    unsigned int ret = 0;
    for (unsigned int n = 1; n <= N; n++)
    {
        const unsigned int n_squared = n * n;
        ret += n_squared;
    }
    return ret;
}

Damit soll vermieden werden, dem Funktionsumfang Variablen hinzuzufügen, die nur für einen bestimmten Block relevant sind. Dies verhindert beispielsweise Fehler, bei denen die generische Schleifenvariable i versehentlich bereits auf einen anderen Wert gesetzt wurde. In diesem Beispiel würde der Ausdruck n * n im Allgemeinen keiner Hilfsvariablen zugewiesen, und der Körper der Schleife würde einfach ret += n * n geschrieben, aber in komplizierteren Beispielen sind Hilfsvariablen nützlich.

Blöcke werden hauptsächlich für den Kontrollfluss verwendet, z. B. mit if-Anweisungen, while-Schleifen und for-Schleifen. In diesen Fällen bedeutet Blockumfang, dass der Umfang der Variablen von der Struktur des Ausführungsflusses einer Funktion abhängt. Programmiersprachen mit Blockbereich erlauben jedoch typischerweise auch die Verwendung von "nackten" Blöcken, deren einziger Zweck darin besteht, eine fein abgestimmte Steuerung des variablen Bereichs zu ermöglichen. Beispielsweise kann eine Hilfsvariable in einem Block definiert, dann verwendet (beispielsweise zu einer Variablen mit Funktionsumfang hinzugefügt) und verworfen werden, wenn der Block endet, oder eine while-Schleife kann in einem Block eingeschlossen sein, der die innerhalb der Schleife verwendeten Variablen initialisiert das sollte nur einmal initialisiert werden.

Eine Feinheit mehrerer Programmiersprachen wie C besteht darin, dass Blockbereichsvariablen nicht nur innerhalb des Blockkörpers, sondern auch innerhalb der Steueranweisung deklariert werden können, wenn irgendein. Dies ist analog zu Funktionsparametern, die in der Funktionsdeklaration vor dem Start des Blocks des Funktionskörpers deklariert werden, und im Gültigkeitsbereich für den gesamten Funktionskörper. Dies wird hauptsächlich für Schleifen verwendet, deren Initialisierungsanweisung im Gegensatz zu while-Schleifen von der Schleifenbedingung getrennt ist, und ist eine gebräuchliche Redewendung.

Der Blockbereich kann zum Verdecken verwendet werden. In diesem Beispiel hätte die Hilfsvariable innerhalb des Blocks auch n heißen können, wodurch der Parametername verdeckt wird. Dies wird jedoch aufgrund der Möglichkeit von Fehlern als schlechter Stil angesehen. Darüber hinaus erlauben einige Nachfahren von C, wie Java und C#, trotz der Unterstützung des Blockbereichs nicht, dass eine lokale Variable eine andere versteckt, da eine lokale Variable vor dem Ende einer Funktion den Gültigkeitsbereich verlassen kann. In solchen Sprachen würde die versuchte Deklaration des zweiten n zu einem Syntaxfehler führen, und eine der Variablen müsste umbenannt werden.

Beispiel

Die Benutzung von Sichtbarkeiten kann beispielsweise folgendermaßen aussehen (PHP[8]):

<?php
class SampleClass
{
    public $public = 'Public';
    protected $protected = 'Protected';
    private $private = 'Private';

    public function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}

$obj = new SampleClass();
echo $obj->public; // Funktioniert
echo $obj->protected; // Fataler Fehler
echo $obj->private; // Fataler Fehler
$obj->printHello(); // Zeigt Public, Protected und Private

Siehe auch

Literatur

Einzelnachweise

  1. https://www.rheinwerk-verlag.de/openbook/#mjf5b3fff9748ae6323d1923016a906a8f
  2. a b Schnittstellen, in: Strukturierte Programmierung, Wikibook, abgerufen am 6. September 2018
  3. Björn und Britta Petri: Modifikatoren, Java-Tutorial, 2010–2018, abgerufen am 6. September 2018
  4. https://www.php.net/manual/de/language.oop5.visibility.php
  5. a b Hanspeter Mössenböck, Niklaus Wirth: Declarations and scope rules, in: The Programming Language Oberon-2, Institut für Computersysteme, ETH Zürich, October 1993, abgerufen am 6. September 2018
  6. Variablen und Methoden, in: Strukturierte Programmierung, Wikibook, abgerufen am 6. September 2018
  7. tutorialspoint.com: C - Scope Rules
  8. PHP: Sichtbarkeit - Manual. Abgerufen am 28. August 2018.