Fachkonzept - Lokale Variablen
Zwischenergebnisse innerhalb einer Methode
Bisher haben wir Werte vor allem in Attributen gespeichert. Attribute beschreiben die Eigenschaften eines Objekts und stehen in der ganzen Klasse zur Verfügung. Häufig braucht man einen Wert aber nur kurz innerhalb einer einzigen Methode – etwa um ein Zwischenergebnis festzuhalten oder einem Ergebnis einen Namen zu geben. Dafür ein Attribut anzulegen, wäre unnötig und sogar irreführend.
Für solche Fälle gibt es lokale Variablen.
Sie werden direkt im Rumpf einer Methode mit val oder
var deklariert – genau wie Attribute, nur eben innerhalb der Methode.
Als Beispiel betrachten wir ein einfaches Konto:
class Konto(val inhaber: String) {
var kontostand = 0
fun zinsenGutschreiben() {
val zinsen = kontostand * 2 / 100 // lokale Variable als Zwischenergebnis
kontostand = kontostand + zinsen
}
}
fun main() {
val konto = Konto("Mia")
konto.kontostand = 1000
konto.zinsenGutschreiben()
println("Neuer Kontostand: ${konto.kontostand}")
}
Hier ist zinsen eine lokale Variable. Sie hält das Zwischenergebnis
der Zinsberechnung fest, damit man es anschließend zum Kontostand addieren kann.
Sobald die Methode fertig ist, wird die Variable nicht mehr gebraucht.
Gültigkeitsbereich
Eine lokale Variable existiert nur innerhalb des Blocks, in dem sie deklariert wurde. Diesen Bereich nennt man ihren Gültigkeitsbereich. Außerhalb dieses Blocks ist die Variable schlicht nicht bekannt – ein Zugriff von außen ist nicht möglich.
Im folgenden Beispiel wird die Variable warnung innerhalb des
if-Blocks deklariert. Der Versuch, sie danach außerhalb dieses
Blocks zu verwenden, schlägt fehl:
class Konto(val inhaber: String) {
var kontostand = 0
fun monatsbericht() {
if (kontostand < 0) {
val warnung = "Konto im Minus!"
}
println(warnung) // Fehler! warnung ist hier nicht bekannt
}
}
fun main() {
val konto = Konto("Mia")
konto.monatsbericht()
}
Die Variable warnung „lebt“ nur innerhalb der geschweiften
Klammern des if-Blocks. Außerhalb davon kennt Kotlin sie nicht.
Damit das Beispiel funktioniert, müsste man die Variable weiter oben – im Rumpf
der Methode selbst – deklarieren.
Lokale Variablen und Attribute
Lokale Variablen und Attribute sehen auf den ersten Blick ähnlich aus, haben aber sehr unterschiedliche Aufgaben. Der wichtigste Unterschied liegt darin, wie lange sie leben und wo sie sichtbar sind.
Ein Attribut gehört zum Objekt. Es wird mit dem Objekt erzeugt, behält seinen Wert über mehrere Methodenaufrufe hinweg und ist in der ganzen Klasse sichtbar.
Eine lokale Variable gehört zur Methode. Sie entsteht bei jedem Aufruf der Methode neu, verschwindet am Ende des Blocks wieder und ist nur innerhalb ihres Gültigkeitsbereichs sichtbar.
Im Konto ist kontostand ein Attribut: Es bleibt über alle
Methodenaufrufe hinweg erhalten und beschreibt den Zustand des Objekts.
Die Variable zinsen war dagegen nur eine lokale Variable der
Methode zinsenGutschreiben(). Eine andere Methode kann nicht auf
sie zugreifen:
class Konto(val inhaber: String) {
var kontostand = 0 // Attribut: bleibt erhalten
fun zinsenGutschreiben() {
val zinsen = kontostand * 2 / 100 // lokale Variable
kontostand = kontostand + zinsen
}
fun zeigeZinsen() {
println(zinsen) // Fehler! zinsen gehört nur zu zinsenGutschreiben()
}
}
fun main() {
val konto = Konto("Mia")
konto.zeigeZinsen()
}
Soll ein Wert über mehrere Methoden hinweg verfügbar sein – also zum „Gedächtnis“ des Objekts gehören –, dann muss er als Attribut gespeichert werden. Wird er hingegen nur kurz innerhalb einer Methode gebraucht, ist eine lokale Variable die richtige und übersichtlichere Wahl.
val und var auch lokal
Wie bei Attributen gilt auch bei lokalen Variablen: Mit val legt man
einen unveränderlichen Wert fest, mit var eine veränderliche
Variable.
Man sollte auch lokal bevorzugt val verwenden und nur dann
var einsetzen, wenn sich der Wert tatsächlich ändern muss.
Das macht Methoden leichter lesbar und verhindert unbeabsichtigte Änderungen.
fun quadratsumme(bis: Int): Int {
var gesamt = 0 // var, weil sich der Zähler ändert
for (zahl in 1..bis) {
val beitrag = zahl * zahl // val, pro Durchlauf neu gesetzt
gesamt = gesamt + beitrag
}
return gesamt
}
fun main() {
println("Quadratsumme bis 4: ${quadratsumme(4)}")
}
Die Variable gesamt wird mit var deklariert, weil
sie in jedem Durchlauf vergrößert wird. Die Hilfsvariable beitrag
bekommt dagegen in jedem Durchlauf einen neuen Wert zugewiesen, ändert sich aber
innerhalb eines Durchlaufs nicht – deshalb genügt val.
Beachte, dass gesamt außerhalb der Schleife deklariert wird:
Würde man es innerhalb des Schleifenrumpfs anlegen, entstünde es bei jedem
Durchlauf neu und könnte nicht aufsummieren.
Lokale Variablen speichern Zwischenergebnisse innerhalb einer Methode. Sie entstehen bei jedem Methodenaufruf neu, gelten nur in ihrem Block (Gültigkeitsbereich) und verschwinden danach wieder. Werte, die ein Objekt dauerhaft behalten soll, gehören dagegen in Attribute.