1. ホーム
  2. java

[解決済み] Option[T]クラスのポイントは何でしょうか?

2023-06-21 23:55:43

質問

の意味がよくわかりません。 Option[T] クラスの意味がわかりません。つまり None よりも null .

例えば、こんなコードを考えてみましょう。

object Main{
  class Person(name: String, var age: int){
    def display = println(name+" "+age)
  }

  def getPerson1: Person = {
    // returns a Person instance or null
  }

  def getPerson2: Option[Person] = {
    // returns either Some[Person] or None
  }

  def main(argv: Array[String]): Unit = {
    val p = getPerson1
    if (p!=null) p.display

    getPerson2 match{
      case Some(person) => person.display
      case None => /* Do nothing */
    }
  }
}

ここで、メソッド getPerson1 が返す null を返すと、その後に行われる呼び出しは display の一行目にある main で失敗するはずです。 NPE . 同様に getPerson2 が返す None を返します。 display を呼び出すと、また同じようなエラーで失敗します。

もしそうなら,なぜScalaは新しい値ラッパー( Option[T] ) を導入することで物事を複雑にしているのでしょうか?

UPDATEです。

私は以下のようにコードを編集しました。 ミッチ の提案に従って私のコードを編集しました。私は、まだ Option[T] . 私は、例外的な null または None のどちらを使ってもいいのですが、 :(

私が正しく理解しているのであれば マイケルの返信 の唯一の利点は Option[T] は、プログラマに明示的に このメソッドは None を返すかもしれない ? この設計上の選択の背後にある理由はこれだけでしょうか?

どのように解決するのですか?

のポイントを押さえます。 Option を決して使わないようにすれば、よりよく理解できるようになるでしょう。 get . というのも get は "ok, send me back to null-land" と等価だからです。

では、あなたのその例を見てみましょう。あなたはどのように display を使わずに get ? 以下はその代替案です。

getPerson2 foreach (_.display)
for (person <- getPerson2) person.display
getPerson2 match {
  case Some(person) => person.display
  case _ =>
}
getPerson2.getOrElse(Person("Unknown", 0)).display

この選択肢のどれをとっても display を呼び出すことはできません。

なぜかというと get が存在する理由ですが、Scalaはあなたのコードがどのように書かれるべきかを教えてはくれません。しかし、もしあなたがセーフティネットなしに戻りたいのであれば、それはあなたの選択です。


あなたはここで釘付けになりました。

<ブロッククオート

はOption[T]の唯一の利点です。 プログラマに明示的に プログラマに伝えることです。 ということを明示的にプログラマに伝えることです。

ただし、"only"を除きます。しかし、別の言い方で言い直します。 メイン の利点は Option[T] を超える T は型安全性です。これは T メソッドを送ることがないようにします。

両方のケースでnullかどうかをテストしなければならないと言いましたが、もしnullをチェックしなければならないことを忘れたり、知らなかったりしたら、コンパイラは教えてくれるでしょうか?それともユーザーが教えてくれるのでしょうか?

もちろん、Javaとの相互運用性のために、ScalaはJavaと同じようにnullを許容します。ですから、もしあなたがJavaのライブラリを使うなら、もしあなたがひどく書かれたScalaのライブラリを使うなら、あるいは、もしあなたがひどく書かれた 個人 Scalaのライブラリを使っていても、NULLポインタを扱わなければならないのです。

の他の二つの重要な利点は Option が思い当たります。

  • ドキュメント:メソッドタイプのシグネチャは、オブジェクトが常に返されるのかどうかを教えてくれます。

  • モナド的なコンポーザビリティ。

後者は完全に理解するにはもっと時間がかかりますし、複雑なコードでこそ力を発揮するので、単純な例にはあまり向いていません。そこで、以下に例を挙げますが、すでに理解している人以外にはほとんど意味がないことはよく承知しています。

for {
  person <- getUsers
  email <- person.getEmail // Assuming getEmail returns Option[String]
} yield (person, email)