Scala模式与选项的混淆[任何
-
05-10-2019 - |
题
我有以下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)
什么是解释?
作为第二个问题,我得到了 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
解决方案
这是由于类型呼吸造成的。 JVM不知道任何类型的参数,除了数组。因此,Scala代码无法检查 Option
是一个 Option[Int]
或一个 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
是,但是其内容的类型是什么 - 假设有任何内容。一种 None
将落到默认情况下。
其他提示
有关类型参数的任何信息仅在编译时可用,而不是在运行时(这被称为类型擦除)。这意味着在运行时没有区别 Option[String]
和 Option[Int]
, ,因此类型上的任何模式匹配 Option[String]
, ,也将匹配 Option[Int]
因为在运行时两者都是 Option
.
由于这几乎不是您打算的,因此您会受到警告。避免警告的唯一方法不是在运行时检查某些东西的通用类型(这很好,因为无论如何您都不喜欢它)。
没有办法检查是否 Option
是一个 Option[Int]
或一个 Option[String]
在运行时(除了检查内容外是否是 Some
).
如前所述,您在这里反对擦除。
对于解决方案...与Scala Actor合作的情况是正常的,可以为您可能发送的每种消息类型定义案例类:
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 _ =>
}
}
}