34

次のScalaコードがあります。

import scala.actors.Actor

object Alice extends Actor {
  this.start
  def act{
    loop{
      react {
        case "Hello" => sender ! "Hi"
        case i:Int => sender ! 0
      }
    }
  }
}
object Test {
  def test = {
    (Alice !? (100, "Hello")) match {
      case i:Some[Int] => println ("Int received "+i)
      case s:Some[String] => println ("String received "+s)
      case _ =>
    }
    (Alice !? (100, 1)) match {
      case i:Some[Int] => println ("Int received "+i)
      case s:Some[String] => println ("String received "+s)
      case _ =>
    }
  }
}

を実行した後Test.test、出力が得られます。

scala> Test.test
Int received Some(Hi)
Int received Some(0)

私は出力を期待していた

String received Some(Hi)
Int received Some(0)

説明は何ですか?

2 番目の質問として、unchecked次のように上記の警告が表示されます。

C:\scalac -unchecked a.scala
a.scala:17: warning: non variable type-argument Int in type pattern Some[Int] is unchecked since it is eliminated by erasure
      case i:Some[Int] => println ("Int received "+i)
             ^
a.scala:18: warning: non variable type-argument String in type pattern Some[String] is unchecked since it is eliminated by erasure
      case s:Some[String] => println ("String received "+s)
             ^
a.scala:22: warning: non variable type-argument Int in type pattern Some[Int] is unchecked since it is eliminated by erasure
      case i:Some[Int] => println ("Int received "+i)
             ^
a.scala:23: warning: non variable type-argument String in type pattern Some[String] is unchecked since it is eliminated by erasure
      case s:Some[String] => println ("String received "+s)
             ^
four warnings found

警告を回避するにはどうすればよいですか?

編集:提案をありがとう。ダニエルのアイデアは素晴らしいですが、以下の例のように、ジェネリック型では機能しないようです

def test[T] = (Alice !? (100, "Hello")) match { 
   case Some(i: Int) => println ("Int received "+i) 
   case Some(t: T) => println ("T received ") 
   case _ =>  
}

次のエラー警告が発生します。warning: abstract type T in type pattern T is unchecked since it is eliminated by erasure

4

3 に答える 3

50

これは型消去によるものです。JVM は、配列以外の型パラメーターを認識しません。そのため、Scala コードは anOptionが anOption[Int]かan かをチェックできませんOption[String]-- その情報は消去されています。

ただし、次の方法でコードを修正できます。

object Test {
  def test = {
    (Alice !? (100, "Hello")) match {
      case Some(i: Int) => println ("Int received "+i)
      case Some(s: String) => println ("String received "+s)
      case _ =>
    }
    (Alice !? (100, 1)) match {
      case Some(i: Int) => println ("Int received "+i)
      case Some(s: String) => println ("String received "+s)
      case _ =>
    }
  }
}

このようにして、のタイプが何であるかをテストするのではなくOption、そのコンテンツのタイプが何であるかをテストします-コンテンツがあると仮定します。ANoneはデフォルトのケースにフォールスルーします。

于 2010-09-24T16:48:52.180 に答える
8

型パラメーターに関する情報は、実行時ではなく、コンパイル時にのみ使用できます (これは型消去と呼ばれます)。Option[String]これは、実行時に と の間に違いがないことを意味します。つまり、実行Option[Int]Option[String]Option[Int]両方がちょうどOption.

これはほとんどの場合意図したものではないため、警告が表示されます。警告を回避する唯一の方法は、実行時に何かのジェネリック型をチェックしないことです (これは、とにかく希望どおりに機能しないため、問題ありません)。

Option実行時にが であるOption[Int]かであるかを確認する方法はありませんOption[String](コンテンツが であるかどうかを検査する以外にSome)。

于 2010-09-24T15:16:07.823 に答える
2

すでに述べたように、ここでは消去に反対しています。

解決策として... Scala アクターでは、送信する可能性のある各メッセージ タイプのケース クラスを定義するのが普通です。

case class MessageTypeA(s : String)
case class MessageTypeB(i : Int)

object Alice extends Actor {
  this.start
  def act{
    loop{
      react {
        case "Hello" => sender ! MessageTypeA("Hi")
        case i:Int => sender ! MessageTypeB(0)
      }
    }
  }
}
object Test {
  def test = {
    (Alice !? (100, "Hello")) match {
      case Some(MessageTypeB(i)) => println ("Int received "+i)
      case Some(MessageTypeA(s)) => println ("String received "+s)
      case _ =>
    }
    (Alice !? (100, 1)) match {
      case Some(MessageTypeB(i)) => println ("Int received " + i)
      case Some(MessageTypeA(s)) => println ("String received " + s)
      case _ =>
    }
  }
}
于 2010-09-24T16:40:34.313 に答える