Verstehen von Optionen in Scala

Suraj P 12 Juli 2022
  1. Der Typ Option in Scala
  2. Abrufen des Wertes der Option in Scala
  3. die Option als Container in Scala
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:

  1. Typsicherheit: Wir können die optionalen Werte parametrieren.
  2. 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.

  1. isEmpty: Diese Methode gibt true zurück, wenn das Objekt None ist.
  2. nonEmpty: Diese Methode gibt true zurück, wenn das Objekt Some ist.
  3. isDefined: Diese Methode gibt true zurück, wenn das Objekt Some 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.

  1. getOrElse: Diese Methode ruft Werte ab, wenn das Objekt Some ist; Andernfalls wird ein Standardwert zurückgegeben.
  2. orElse: Diese Methode ruft Werte ab, wenn das Objekt Some ist; andernfalls gibt eine alternate-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:

  1. filter: Diese Methode gibt Option zurück, wenn der Wert Options Some ist und die gelieferte Funktion true zurückgibt.
  2. exists: Diese Methode gibt true zurück, wenn die Option gesetzt ist und die mitgelieferte Funktion true zurückgibt.
  3. forall: Verhält sich wie die Methode exists.

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.

Autor: Suraj P
Suraj P avatar Suraj P avatar

A technophile and a Big Data developer by passion. Loves developing advance C++ and Java applications in free time works as SME at Chegg where I help students with there doubts and assignments in the field of Computer Science.

LinkedIn GitHub