Klassensystem
- Klassenhierarchie
- Basis Typen
- Wertebereich
- Scala Basis-Typen vs. Java primitive Typen
- Literale
- Wertetypen (value classes)
Stand: 10. August 2019
Scala-Version: 2.13.0
Klassenhierarchie
Die nachfolgende Grafik gibt einen Überblick über die Scala - Klassenhierarchie 1.
Basis Typen
In Scala gibt es keine primitive Datentypen. Alle Typen sind
Objekte. In Scala gibt es jedoch Objekttypen, die den primitiven
Datentypen in Java zugeordnet werden können. Eine
Sonderstellung unter den Basis-Typen stellt der Typ String dar,
der auch in Java ein Objekt ist.
Nachfolgend eine Auflistung der Basis Typen in Scala:
Die Typen Int, Long, Short, Byte und Char werden als integrale
Typen bezeichnet. Die integralen Typen und die Typen Float und Double
werden als numerische Typen bezeichnet.
Wertebereich
Der Wertebereich der Basis Typen entspricht dem der entsprechenden primitiven Typen in Java. Die bei numerischen Typen angegebene Bytezahl entspricht dem darzustellenden Wertebereich. Da die Basistypen vollwertige Objekte sind, benötigen diese eine größere Anzahl Bytes um diese im Speicher abzulegen.
Wertebereich der numerischen Basistypen
| Basistyp | Wertebereich | ||||
| Byte | -128 | (-27) | bis | 127 | (27-1) |
| Char | 0 | bis | 216-1 | ||
| Short | -215 | bis | 215-1 | ||
| Int | -231 | bis | 231-1 | ||
| Long | -263 | bis | 263-1 | ||
| Float | ±3.4028235E38 | ||||
| Double | ±1.7976931348623157E308 | ||||
| Basistyp | Bytes |
| Byte | 1 |
| Char | 2 |
| Short | 2 |
| Int | 4 |
| Long | 8 |
| Float | 4 |
| Double | 8 |
Wertebereich von String und Boolean
Ein Boolean kann die Werte true oder false
annehmen. Ein String ist eine beliebig lange Sequenz von Elementen des Typs Char .
Scala Basis-Typen vs. Java primitive Typen
Da Scala vollwertige Objekte anstatt der primitiven Typen in Java verwendet, lässt vermuten, dass ein Scala Programm langsamer abläuft als ein Java Programm. Dies ist in der Regel nicht der Fall. Scala greift, wo möglich, auf primitive Typen in den Klassen zurück, sodass der Objekt-Overhead sich nicht wesentlich auf die Ausführungsgeschwindigkeit eines Scala Programms auswirkt. Scala Programme sind in der Ablaufgeschwindigkeit vergleichbar zu entsprechenden Java Programmen.
Durchgeführte Geschwindigkeitsmessungen des Autors anhand von Berechnungsprogrammen zeigen, dass Scala Programme oft nur unwesentlich langsamer sind und zum Teil auch schneller als die entsprechenden Java Programme. Diese Beobachtung deckt sich mit Angaben anderer Quellen zu Scala.
Literale
Literale sind vordefinierte Konstanten für Basistypen. Literale können überall dort im Quelltext verwendet werden, wo Konstanten-Variablen im Quelltext eingesetzt werden können.
Boolean Literale
Der Datentyp Boolean kennt genau zwei Literale:
truefalse
welche den Wahrheitswerten wahr und falsch entsprechen.
Char (Character) Literale
Ein Char Literal ist ein einzelnes, druckbares Unicode Zeichen
oder eine Escape Sequenz in einfachen Anführungszeichen. Für Unicode
Zeichen im Bereich von 0 bis 255 ist auch eine Angabe in oktal Form möglich.
Nachfolgend einige Beispiele für Char Literale:
| 'A' | Das Zeichen A |
| '\u0042' | Das Zeichen B als Unicode Escape Sequenz |
| '\141' | Das Zeichen a als Oktal Escape Sequenz |
| '\n' | Der Zeilenumbruch |
Gleitkomma Literale
Double Literale
Ein Double Literal besteht aus einer Reihe von Zahlen und mindestens
einem der folgenden Elemente:
- Einem Dezimalpunkt (.)
-
Dem Exponentialzeichen
Eoderemit zusätzlicher Angabe des Exponenten zur Basis 10 -
Die Angabe von
Doderdzur Kennzeichnung desDoubleLiterals
Nachfolgend einige Beispiele für Double Literale:
123.45
.123
123E0
123d
123D
123.45E0d
Ein Literal in der Form 123. sollte man nicht mehr verwenden. Nach aktuellem Stand (23. November 2011),
wird ein Literal, dass auf einem Punkt endet in der Version 2.10 von Scala als deprecated gekennzeichnet und
wird mit der Version 2.11 sogar nicht mehr al Double Literal erkannt.
Float Literale
Für Float Literale gelten zunächst die gleichen Regeln wie
für Double Literale mit der Erweiterung, dass bei einem
Float Literal ein "f" oder ein "F" am Ende des
Literals angegeben werden muss. Da ein Float Literal ein "f"
oder "F" am Ende aufweisen muss, ist bei einem Float der
Dezimalpunkt optional.
Beispiele für Float Literale sind:
123.45f
.123F
123.f
123F
123E0f
Ganzzahl Literale
Int Literale
In Scala unterscheiden wir wie in Java je nach Schreibweise 3 unterschiedliche Typen von Int Literalen:
- Dezimale
IntLiterale - Hexadezimale
IntLiterale - Oktale
IntLiterale
Ein dezimaler Int Literal besteht aus den Ziffern 0 bis 9 und dem Minuszeichen
"-" für negative Werte. In der Dezimalschreibweise
darf ein Int Literal nicht mit "0" oder "-0" beginnen (siehe Oktalschreibweise / Hexadezimalschreibweise).
Nachfolgend einige Beispiele für Int Literale in Dezimalschreibweise:
256
748
-4656
-43573
In der Oktalschreibweise beginnt ein Int Literal mit "0" oder "-0"-
In dieser Schreibweise sind ein führendes Minuszeichen "-" und die Ziffern
0 bis 7 zur Bildung des Literals erlaubt. Nachfolgend einige Beispiele für Int
Literale in Oktalschreibweise:
0123
-0653
0333
04563
Um ein Int Literal in Hexadezimal anzugeben, muss das Literal mit
"0x" oder "0X", mit einem optionalen "-" für negative
Werte, eingeleitet werden. Im Anschluss folgt der Wert des Literals in hexadezimaler Schreibweise,
wo zusätzlich zu den Ziffern 0 bis 9 noch die Buchstaben A bis F bzw. a bis f
zur Bildung des Literals herangezogen werden können. Nachfolgend einige Beispiele
für Int Literale in hexadezimaler Schreibweise.
0x123
0xff
-0x00ff
-0X54ab
0xabcdef
Long Literale
Für Long Literale gelten dieselben Regeln wie für
Int Literale. Dies gilt auch für die Angabe in Oktal-
bzw. Hexadezimalschreibweise.
Die Unterscheidung zu anderen Ganzzahl Literalen erfolgt durch
die Endung des Literals mit dem Buchstaben "l" oder
"L". Nachfolgend einige Beispiele für Long Literale:
123l
123L
0x235L
0324l
0xffL
Byte und Short Literale
Für Byte Literale gelten im Grunde dieselben dieselben Bedingungen wie für
Int Literale. Voraussetzung ist jedoch, dass Sie einen Wert im Wertebereich
des Basistypen darstellen und einer entsprechenden Variable zugewiesen werden.
Nachfolgend einige Beispiele für Byte und Short Literale:
val value1 : Short = 123
val value2 : Byte = 123
val value3 : Byte = 0xf
val value4 : Short = 012
String Literale
Ein String Literal ist eine Sequenz von Char - Zeichen in doppelten
Anführungszeichen. Beispiel für String Literale sind:
"Ich""123""test"
Das Anführungszeichen, der Backslash bzw. ein beliebiges Unicodezeichen können in einem String durch einen Backslash maskiert werden.
Müssen in einem String Literal eine Vielzahl von (direkt eingebbaren)
Zeichen maskiert werden, kann ein String Literal in dreifachen, doppelten
Anführungszeichen gesetzt werden. Dies führt dazu, dass der Backslash nicht
zur Maskierung herangezogen wird und auch alle anderen Zeichen wie angegeben behandelt werden.
Ein Beispiel für einen derartigen String Literal ist:
"""\"1'\""" welches der Zeichenkette
\"1'\ entspricht.
Wertetypen (value classes)
Scala kennt 9 eingebaute Wertetypen (value classes):
IntLongShortByteFloatDoubleCharBooleanUnit
Wertetypen sind in Scala vom Typ AnyVal abgeleitet. Wertetypen
können in Scala nicht als Basisklasse für eigene Erweiterungen verwendet werden.
Seit Scala 2.10 ist es jedoch möglich, eigene Klassen von AnyVal
abzuleiten. Alle Klassen, die nicht zu den Wertetypen gehören, sind Referenztypen und
haben die gemeinsame Basisklasse AnyRef.
Mit Ausnahme von Unit entsprechen die Wertetypen den primitiven Datentypen von Java.
Der Datentyp Unit kann mit dem Typ void aus Java verglichen werden.
Der Typ Unit wird häufig als Rückgabetyp von Methoden eingesetzt,
welche nur wegen ihrer Seiteneffekte aufgerufen werden und kein eigentliches Ergebnis
als Rückgabewert liefern.
Stellen wir uns nun der Frage, warum wir eine Unterscheidung zwischen Wertetypen und Referenztypen vornehmen. Die Arbeit mit primitiven Datentypen kann innerhalb der JVM sehr effizient geschehen. Es ist nicht notwendig Objekte zu erzeugen (zu verwalten) um mit primitiven Datentypen etwa Berechnungen durchzuführen. Würden wir in Scala immer mit den vollständigen Objekten arbeiten hätten wir einen gewaltigen Performance Nachteil gegenüber Java. Wie schon angedeutet ist dies nicht der Fall. Wo immer es möglich ist, arbeitetet die JVM bei Wertetypen mit primitiven Datentypen statt der vollwertigen Objekten. Ein "boxing" bzw. "unboxing"2 findet nur dann statt, wenn Objektfunktionalität benötigt wird, welche über die Eigenschaften der primitiven Datentypen hinausgeht.
1 Vergleiche [SQ4]
2 Als boxing / unboxing beschreibt man die Umwandlung eines primitiven Datentyps in ein Objekt bzw. die Umwandlung von einem Objekt in einen primitiven Datentyp.