Verstehen von Optionen in Scala
In diesem Artikel lernen wir, wie man mit optionalen Datenelementen in Scala arbeitet. Option
in Scala helfen uns, robusten Code zu schreiben.
Der Typ Option
in Scala
Option[T]
in einer Scala ist ein container
, der null oder einen Wert eines bestimmten Typs speichert. Bei der Verwaltung optionaler Werte mit Scalas Option
können wir zwei Dinge sicherstellen:
- Typsicherheit: Wir können die optionalen Werte parametrieren.
- Funktionales Bewusstsein: Der Typ
option
bietet viele funktionale Fähigkeiten, die sicherstellen, dass weniger Fehler im Programm erzeugt werden.
In Scala wird eine Option[T]
entweder durch ein Some[T]
- oder None[T]
-Objekt dargestellt. Hier ist scala.Option
die Basisklasse, die abstrakt und erweitert ist, wodurch sich die Option
in Scala wie ein Container verhält.
Denken Sie daran, dass die Klasse Option
und ihre Unterklassen einen konkreten Typ benötigen. Sie können entweder explizit oder wie in der folgenden Syntax abgeleitet sein.
Beispiel:
val obj1: Option[Int] = None
val obj2 = Some(100)
Hier sind obj1
und obj2
Objekte von Option[Int]
. Eine häufig gestellte Frage ist, wie man überprüft, ob unsere Option
Some
oder None
ist?
Um dieses Problem zu lösen, haben wir die folgenden Funktionen.
isEmpty
: Diese Methode gibttrue
zurück, wenn das ObjektNone
ist.nonEmpty
: Diese Methode gibttrue
zurück, wenn das ObjektSome
ist.isDefined
: Diese Methode gibttrue
zurück, wenn das ObjektSome
ist.
Abrufen des Wertes der Option in Scala
Wir können die Methode get
verwenden, um den Wert Options
abzurufen. Wenn die Methode get
auf einem Objekt von None
aufgerufen wird, wird NoSuchElementException
ausgelöst, was auch als success bias
bezeichnet wird.
Beispielcode:
val obj1: Option[Int]= ...
val v1 = if (obj1.isDefined)
{
obj1.get
}
else
{
0
}
Der obige Code kann auch mit Musterabgleich geschrieben werden.
Beispielcode:
val obj1: Option[Int]= ...
val v1 = obj1 match {
case Some(temp) =>
temp
case None =>
0
}
Wir haben auch andere Methoden wie getOrElse
und orElse
, um Werte abzurufen.
getOrElse
: Diese Methode ruft Werte ab, wenn das ObjektSome
ist; Andernfalls wird ein Standardwert zurückgegeben.orElse
: Diese Methode ruft Werte ab, wenn das ObjektSome
ist; andernfalls gibt einealternate
-Option zurück.
Wenn der optionale Wert nicht gesetzt ist, ist die Methode getOrElse
sehr nützlich, da wir einen Standardwert zurückgeben können.
Syntax:
val v1 = obj1.getOrElse(0)
die Option
als Container in Scala
Wie wir gesehen haben, ist Option
ein Container in Scala für einen anderen Wert, genauso wie wir eine List
durchlaufen, können wir eine Option
durchlaufen.
Sehen wir uns einige Methoden für diesen Container an. Syntax der Methode Option.map
in Scala:
final def map[Y](f: (X) => Y): Option[Y]
Beispielcode:
val obj1: Option[Int] = Some(100)
assert(obj1.map(_.toString).contains("100"))
assert(obj1.map(_ * 2.0).contains(200))
val obj2: Option[Int] = None
assert(obj2.map(_.toString).isEmpty)
Im obigen Beispiel haben wir die Methode Option.map
verwendet, um die enthaltenen Werte in einen anderen Typ zu konvertieren. Die Methode Option.map
könnte auch verwendet werden, um die Flusssteuerung des Programms zu beeinflussen.
Beispielcode:
val obj1: Option[Int] = Some(10)
val obj2: Option[Int] = None
def mul(n: Int): Int = n * 2
assert(obj1.map(mul).contains(20))
assert(obj2.map(mul).isEmpty)
Hier haben wir zwei Objekte von Option[Int]
erstellt, das erste Objekt hat den Wert 10
und das zweite ist leer. Dann haben wir eine Methode mul
definiert, die die Eingabe mit 2
multipliziert.
Schliesslich mappen wir obj1
und obj2
mit der mul
-Methode. Das Mapping von obj1 gibt uns Some(20)
und das Mapping von obj2 ergibt None
.
Dabei ist zu beachten, dass beim zweiten Aufruf obj2.map(mul)
die Methode mul
gar nicht aufgerufen wird. Wir können auch eine Flusskontrolle mit Filterung durchführen.
Dazu haben wir viele Methoden:
filter
: Diese Methode gibtOption
zurück, wenn der WertOptions
Some
ist und die gelieferte Funktiontrue
zurückgibt.exists
: Diese Methode gibttrue
zurück, wenn dieOption
gesetzt ist und die mitgelieferte Funktiontrue
zurückgibt.forall
: Verhält sich wie die Methodeexists
.
Mit diesen Funktionen können wir den Code sehr prägnant schreiben.
Lassen Sie uns ein Beispiel haben, wo wir das Team mit der höchsten Punktzahl finden.
Beispielcode:
def highScoringTeam(playerA: Player, playerB: Player, tournament: Tournament): Option[(Player, Int)] =
{ getTopScore(playerA, tournament).foldRight(getTopScore(playerB, tournament)) {
case (playerAInfo, playerBInfo) => playerBInfo.filter {
case (_, scoreB) => scoreB > playerAInfo._2
}.orElse(Some(playerAInfo))
}
}
Im obigen Code haben wir genutzt, dass Optionen
als Sammlungen verwendet werden können. Der einzige Unterschied besteht darin, dass eine Option höchstens einen Wert haben kann.