Mit den Klassen und (Companion) Objekten
Option, Some und None können wir in Scala optionale
Werte verwalten. Mit diesen Elementen können wir auch das aus Java bekannte null
vermeiden, welches kein Objekt ist, bzw. wir können null-bezogene Werte objektorientiert
verarbeiten.
Option ist die abstrakte Basisklasse für Some und None.
None ist ein Singleton-Objekt
zur Aussage, dass der optionale Wert nicht gegeben ist. Some hingegen enthält einen
existierenden optionalen Wert.
Stellen wir uns nun der Aufgabe Option-Objekte zu erzeugen und einer Variablen
zuweisen können. Lassen wir die null-Vermeidung
erst mal außen vor, bieten sich zwei grundsätzliche Möglichkeiten. Erstens durch Zuweisung
von None und zweitens durch Zuweisung eines parametrisierten Some Objektes.
Sehen wir uns diese Vorgehensweise nun mal an einem kleinen Beispiel an.
object OSN1 {
def main(args: Array[String]): Unit = {
val oNone = None
val oSome: Some[Int] = Some(42)
}
}
None ist in Scala ein Singlton-Objekt,
dass bei erster Verwendung erzeugt wird.
Dieses eine Singleton-Objekt verwenden wir für alle optionalen Werte, dessen
Wert nicht gegeben ist. Die Some-Klasse verwenden wir für alle
optionalen Werte die gegeben sind. Das entsprechende Some-Objekt
kapselt dabei den gegebenen Wert.
null ist in der Java - Welt ein Wert, der für nicht gegeben steht.
null ist kein Objekt und hat keinen Typ. Wir können jeder Referenzvariablen
den Wert null zuweisen, was sogar der initiale Wert ist, sofern wir bei der
Definition einer Variablen keine explizites Objekt der Referenz zuweisen.
Variablen für primitive Datentypen in Java können wir null
nicht als Wert zuweisen.
Auch wenn wir das, wenn irgendwie möglich, vermeiden sollten:
Auch in Scala können wir null als Rückgabewert von Methoden / Funktionen
verwenden oder einer Referenzvariablen zuordnen.
Das Hauptproblem in der Verwendung von null liegt darin, dass null
kein Objekt ist. Das führt unter anderem zu Problemen in der Verarbeitung von
Collections, wenn ein Objekt erwartet und bearbeitet werden soll. Wir müssten dann,
für jede Bearbeitung einen Sonderfall für null betrachten und
auch zumeist programmieren.
In Scala schafft der Datentyp Option mit den zwei Ausprägungen
Some und None Abhilfe. Sollte irgendwo im Programm die
Möglichkeit auftreten, dass ein bestimmter Wert nicht gegeben ist, so verwenden wir
den Datentyp Option. Ist der Wert gegeben "verpacken" wir diesen in
die Ausprägung Some. Ist der Wert nicht gegeben, verwenden wir an dessen
Stelle None.
Die Zuweisung zu Some oder None müssen wir nicht explizit
ausprogrammieren. Wir übergeben einfach den zuzuweisenden Wert an die
apply - Methode
des Option - Companion Objektes.
Ist der übergebene Wert null erhalten wir ein None als
Ergebnis. Andernfalls erhalten wir ein Some Objekt mit dem übergebenen
Wert.
Das nachfolgende Beispiel zeigt die Erzeugung von Option Objekten, deren
Wert möglicherweise nicht gegeben ist (also entsprechend null in Java).
object Main {
def main(args: Array[String]): Unit = {
val avoidNull = new PossibleNull
val myOption1 = Option[String](avoidNull.possibleNullMethod(4))
val myOption2 = Option[String](avoidNull.possibleNullMethod(3))
println(myOption1)
println(myOption2)
}
}
class PossibleNull {
def possibleNullMethod(value: Int): String = {
if (value % 2 == 0) "even"
else null
}
}
Die Ausführung des Programms führt zu folgender Ausgabe auf der Systemausgabe.
Some(even) None
Da Option Objekte None oder Some Ausprägungen sein
können, werden wir für Option Objekte, bei Verwendung, häufig zwei unterschiedliche
Behandlungen programmieren wollen. Hier kommt uns die Methode getOrElse[B >: A](default: ? B): B
von Option entgegen, die bei Some sich selbst und im entgegengesetzten Fall
das als default definierte Objekt zurückgibt .
object GetOrElse {
def main(args: Array[String]): Unit = {
new GetOrElse()
}
}
class GetOrElse() {
def getNullable(nullValue: Boolean): String = {
if (nullValue) return null
else return "Not null"
}
val test1 = Option(getNullable(false))
val test2 = Option(getNullable(true))
println(test1.getOrElse("I'm None"))
println(test2.getOrElse("I'm None"))
}
Die Ausführung des Programms führt zu folgender Ausgabe auf der Systemausgabe:
Not null
I'm None
isDefined prüft, ob das zugehörige Objekt vom Typ Some ist.
Im Falle von Some liefert isDefined true andernfalls false
als Ergebnis.
object ODEF {
def main(args: Array[String]): Unit = {
val someValue: Option[String] = Some("Hello")
val noneValue: Option[String] = None
println(someValue.isDefined)
println(noneValue.isDefined)
}
}
Die Ausführung des Programms führt zu folgender Ausgabe auf der Systemausgabe:
true
false
Daniel Westheide
The Neophyte's Guide to Scala Part 5: The Option Type
http://danielwestheide.com/blog/2012/12/19/the-neophytes-guide-to-scala-part-5-the-option-type.html
Tony Morris
scala.Option Cheat Sheet
http://blog.tmorris.net/posts/scalaoption-cheat-sheet/
http://stackoverflow.com/ 
When to use Option
http://stackoverflow.com/questions/9698391/when-to-use-option
API Dokumentation:
Option (class)

Option (object)

Some

None
