scalatutorial.de

Stufe 2Sprachkern · Lektion 6 von 34

Variablen, Werte und Basistypen

Aktualisiert am 24. September 20263 Min. LesezeitSchritt 1/7 dieser Stufe

In Scala gibt es zwei Arten, einem Namen einen Wert zu geben: val für Werte, die sich nie ändern, und var für Variablen. Dazu kommen die Basistypen für Zahlen, Zeichen und Wahrheitswerte – und ein paar Eigenheiten beim Rechnen.

val und var

 Scala 3
val pi = 3.14159        // unveränderlich
var zaehler = 0         // veränderlich

zaehler = zaehler + 1   // erlaubt
// pi = 3.0             // Fehler: Reassignment to val pi

Ein val ist wie final in Java: Der Name ist fest an einen Wert gebunden. Eine var kann später neu belegt werden. In idiomatischem Scala ist val der Normalfall. Warum? Werte, die sich nicht ändern, sind leichter nachzuvollziehen, lassen sich gefahrlos zwischen Threads teilen und machen Fehler wie „wer hat diese Variable verändert?“ unmöglich.

Typinferenz und Typangaben

Im Beispiel oben steht nirgends ein Typ – der Compiler leitet ihn aus dem Wert ab. Sie können ihn aber jederzeit angeben:

 Scala 3
val anzahl: Int = 42
val preis: Double = 9.99
val name: String = "Ada"
val aktiv: Boolean = true

Eine Typangabe ist sinnvoll, wenn der abgeleitete Typ nicht der gewünschte ist, etwa val x: Long = 5 statt Int.

Die Basistypen

TypBeschreibungBeispiel
Byte, Shortganze Zahlen mit 8 bzw. 16 Bitval b: Byte = 12
Intganze Zahl, 32 Bit42
Longganze Zahl, 64 Bit42L
FloatGleitkommazahl, 32 Bit3.5f
DoubleGleitkommazahl, 64 Bit3.5
Chareinzelnes Zeichen'a'
BooleanWahrheitswerttrue, false
StringZeichenkette (aus Java)"Hallo"
Unit„kein Wert“()

Anders als in Java gibt es keine primitiven Typen, die sich anders verhalten als Objekte: Auch Int hat Methoden, etwa 5.max(9) oder -3.abs. Der Compiler übersetzt sie trotzdem, wo möglich, in schnelle primitive JVM-Werte. Wie die Typen zusammenhängen, zeigt die Hierarchie:

Die Typhierarchie von Scala: Any, AnyVal, AnyRef, Null und NothingAnyAnyValAnyRefIntDoubleBooleanCharUnitStringList[A]eigene KlassenNullNothingNothing ist Untertyp von allem,z. B. der Typ von throw.
Alle Typen erben von Any; Nothing steht ganz unten.

Rechnen mit Zahlen

 Scala 3
val a = 7 / 2        // 3   – ganzzahlige Division
val b = 7 / 2.0      // 3.5 – sobald ein Double beteiligt ist
val c = 7 % 2        // 1   – Rest
val d = math.pow(2, 10)   // 1024.0
val e = math.sqrt(2)      // 1.4142135623730951
val f = BigDecimal("0.1") + BigDecimal("0.2")   // exakt 0.3

Zwei Eigenheiten, die Einsteiger regelmäßig überraschen:

Das Objekt math bündelt mathematische Funktionen wie sin, log, round und floor. Umwandlungen zwischen Zahltypen erledigen Methoden wie toInt, toDouble oder toLong: 3.9.toInt ergibt 3 (es wird abgeschnitten, nicht gerundet).

lazy val

Ein lazy val wird erst beim ersten Zugriff berechnet und danach zwischengespeichert:

 Scala 3
lazy val konfiguration =
  println("lese Datei …")
  scala.io.Source.fromFile("app.conf").mkString

// noch nichts passiert
println(konfiguration.length)   // jetzt wird gelesen
println(konfiguration.length)   // jetzt nicht mehr

Das lohnt sich für teure Berechnungen, die vielleicht gar nicht gebraucht werden.

Schlüsselwörter

Einige Wörter sind reserviert und dürfen nicht als Namen verwendet werden, darunter val, var, def, class, object, trait, if, else, match, case, for, while, yield, new, this, type, import, package und return. Scala 3 hat weitere „weiche“ Schlüsselwörter wie given, using, extension, end oder opaque, die nur an bestimmten Stellen eine Sonderbedeutung haben. Wer einen reservierten Namen trotzdem braucht, etwa für eine Java-Methode namens type, setzt ihn in Backticks, also in Gravis-Zeichen vor und hinter dem Namen.

Passt dazu