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
optionbietet 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 gibttruezurück, wenn das ObjektNoneist.nonEmpty: Diese Methode gibttruezurück, wenn das ObjektSomeist.isDefined: Diese Methode gibttruezurück, wenn das ObjektSomeist.
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 ObjektSomeist; Andernfalls wird ein Standardwert zurückgegeben.orElse: Diese Methode ruft Werte ab, wenn das ObjektSomeist; 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 gibtOptionzurück, wenn der WertOptionsSomeist und die gelieferte Funktiontruezurückgibt.exists: Diese Methode gibttruezurück, wenn dieOptiongesetzt ist und die mitgelieferte Funktiontruezurü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.
