Klassenhierarchie

Die nachfolgende Grafik gibt einen Überblick über die Scala - Klassenhierarchie 1.

Scala Klassenhierarchie


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:

  • true
  • false

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 E oder e mit zusätzlicher Angabe des Exponenten zur Basis 10
  • Die Angabe von D oder d zur Kennzeichnung des Double Literals

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 Int Literale
  • Hexadezimale Int Literale
  • Oktale Int Literale

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):

  • Int
  • Long
  • Short
  • Byte
  • Float
  • Double
  • Char
  • Boolean
  • Unit

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.