Scala-extractors

提供:Dev Guides
移動先:案内検索

Scala-エクストラクター

Scalaのエクストラクターは、メンバーの1つとして unapply というメソッドを持つオブジェクトです。 この適用解除メソッドの目的は、値を一致させて分解することです。 多くの場合、extractorオブジェクトは、値を構築するためのデュアルメソッド apply も定義しますが、これは必須ではありません。

*apply* メソッドと *unapply* メソッドの両方を定義するオブジェクトの例を見てみましょう。 applyメソッドはいつもと同じ意味を持ちます:Testを、メソッドが適用されるのと同じ方法で括弧内の引数に適用できるオブジェクトに変えます。 したがって、Test( "Zara"、 "gmail.com")を記述して、文字列 "[email protected]"を作成できます。
*unapply* メソッドは、Testクラスを *extractor* に変換し、 *apply* の構築プロセスを逆にします。 applyが2つの文字列を受け取り、それらから電子メールアドレス文字列を形成する場合、unapplyは電子メールアドレスを受け取り、潜在的に2つの文字列を返します。アドレスの *user* と *domain* です。
*unapply* は、指定された文字列が電子メールアドレスではない場合も処理する必要があります。 これが、unapplyが文字列のペアに対してOption型を返す理由です。 結果は、文字列strが指定されたユーザーとドメイン部分を持つ電子メールアドレスである場合は* Some(user、domain)*、strが電子メールアドレスでない場合はNoneです。 以下に例を示します。

構文

unapply("[email protected]") equals Some("Zara", "gmail.com")
unapply("Zara Ali") equals None

次のプログラム例は、電子メールアドレスの抽出オブジェクトを示しています。

object Demo {
   def main(args: Array[String]) {
      println ("Apply method : " + apply("Zara", "gmail.com"));
      println ("Unapply method : " + unapply("[email protected]"));
      println ("Unapply method : " + unapply("Zara Ali"));
   }

  //The injection method (optional)
   def apply(user: String, domain: String) = {
      user +"@"+ domain
   }

  //The extraction method (mandatory)
   def unapply(str: String): Option[(String, String)] = {
      val parts = str split "@"

      if (parts.length == 2){
         Some(parts(0), parts(1))
      } else {
         None
      }
   }
}

上記のプログラムを Demo.scala に保存します。 このプログラムをコンパイルして実行するには、次のコマンドを使用します。

コマンド

\>scalac Demo.scala
\>scala Demo

出力

Apply method : [email protected]
Unapply method : Some((Zara,gmail.com))
Unapply method : None

エクストラクタを使用したパターンマッチング

クラスのインスタンスの後に、ゼロ個以上のパラメーターのリストを含む括弧が続く場合、コンパイラーはそのインスタンスで apply メソッドを呼び出します。 オブジェクトとクラスの両方で適用を定義できます。

上記のように、 unapply メソッドの目的は、探している特定の値を抽出することです。 apply とは逆の操作を行います。 match ステートメントを使用して抽出オブジェクトを比較すると、 unapply メソッドが自動的に実行されます。

次のプログラム例を試してください。

object Demo {
   def main(args: Array[String]) {
      val x = Demo(5)
      println(x)

      x match {
         case Demo(num) => println(x+" is bigger two times than "+num)

        //unapply is invoked
         case _ => println("i cannot calculate")
      }
   }
   def apply(x: Int) = x*2
   def unapply(z: Int): Option[Int] = if (z%2==0) Some(z/2) else None
}

上記のプログラムを Demo.scala に保存します。 このプログラムをコンパイルして実行するには、次のコマンドを使用します。

コマンド

\>scalac Demo.scala
\>scala Demo

出力

10
10 is bigger two times than 5