是否可以在没有警告的情况下在演员内部接收元组 "eliminated by erasure"
Is it possible to receive a tuple inside an actor without the warning "eliminated by erasure"
我想知道是否可以在 actor 内部接收元组,而不会收到此警告:
non-variable type argument Long in type pattern (Long, Int) is unchecked since it is eliminated by erasure
尽管代码似乎有效且有效:
override def receive: Receive = {
case tuple: (Long, DateTime) => sendPlace(tuple._1, tuple._2)
}
我是不是漏掉了什么?
元组是通用类型,例如Tuple2[T1, T2]
并且在 JVM 中,这些类型参数被擦除并且不存在于运行时中。网上有很多关于这个话题的。
您的代码有效,但唯一检查消息是否与模式匹配的是消息是否为 Tuple2
,而不是其内部类型。如果这个 actor 得到另一个 Tuple2
,比如 (String, String)
,当你尝试将 String
转换为 Long
时,你将得到一个 class 转换异常,当你试图传递第一个元素时sendPlace
方法。
例如在下面
override def receive: Receive = {
case tuple: (Long, DateTime) => sendPlace(tuple._1, tuple._2)
case tuple: (Int, Int) => sender ! (tuple._1 + tuple._2)
}
第二个模式无法访问,它永远不会匹配,因为任何 Tuple2
将匹配第一个模式并在类型错误时抛出异常。
一般来说,您应该为消息创建大小写 classes。这对消息及其成员都有一个有意义的名称的好处,元组仅说明其类型。您应该在其伴随对象中定义 actor 可以处理的消息。
object BookingActor {
case class BookingRequest(placeId: Long, bookingTime: DateTime)
}
class BookingActor {
import BookingActor._
override def receive: Receive = {
case BookingRequest(id, time) => bookPlace(id, time)
}
// ...
}
写作
case (id: Long, time: DateTime) => sendPlace(id, time)
也会避免未经检查的转换,但 Łukasz 是对的:您应该为此目的定义一个案例 class。
since two applications are communicating together it allows me not to define two times the case class
当然你不应该定义它两次。在两个应用程序都依赖的库中定义一次。这样 1) 您可以明确应用程序通信的位置; 2) 如果您需要更改消息类型(例如添加另一个字段,或更改其中一个字段的类型),您将不太可能忘记更改其中一侧。
Can you just, please, explain why I don't get this warning when it is not in the context of an actor that receives a message?
你做到了:
val x: Any = ("a", "b")
x match {
case tuple: (Long, DateTime) =>
println("shouldn't match, but does")
}
我想知道是否可以在 actor 内部接收元组,而不会收到此警告:
non-variable type argument Long in type pattern (Long, Int) is unchecked since it is eliminated by erasure
尽管代码似乎有效且有效:
override def receive: Receive = {
case tuple: (Long, DateTime) => sendPlace(tuple._1, tuple._2)
}
我是不是漏掉了什么?
元组是通用类型,例如Tuple2[T1, T2]
并且在 JVM 中,这些类型参数被擦除并且不存在于运行时中。网上有很多关于这个话题的。
您的代码有效,但唯一检查消息是否与模式匹配的是消息是否为 Tuple2
,而不是其内部类型。如果这个 actor 得到另一个 Tuple2
,比如 (String, String)
,当你尝试将 String
转换为 Long
时,你将得到一个 class 转换异常,当你试图传递第一个元素时sendPlace
方法。
例如在下面
override def receive: Receive = {
case tuple: (Long, DateTime) => sendPlace(tuple._1, tuple._2)
case tuple: (Int, Int) => sender ! (tuple._1 + tuple._2)
}
第二个模式无法访问,它永远不会匹配,因为任何 Tuple2
将匹配第一个模式并在类型错误时抛出异常。
一般来说,您应该为消息创建大小写 classes。这对消息及其成员都有一个有意义的名称的好处,元组仅说明其类型。您应该在其伴随对象中定义 actor 可以处理的消息。
object BookingActor {
case class BookingRequest(placeId: Long, bookingTime: DateTime)
}
class BookingActor {
import BookingActor._
override def receive: Receive = {
case BookingRequest(id, time) => bookPlace(id, time)
}
// ...
}
写作
case (id: Long, time: DateTime) => sendPlace(id, time)
也会避免未经检查的转换,但 Łukasz 是对的:您应该为此目的定义一个案例 class。
since two applications are communicating together it allows me not to define two times the case class
当然你不应该定义它两次。在两个应用程序都依赖的库中定义一次。这样 1) 您可以明确应用程序通信的位置; 2) 如果您需要更改消息类型(例如添加另一个字段,或更改其中一个字段的类型),您将不太可能忘记更改其中一侧。
Can you just, please, explain why I don't get this warning when it is not in the context of an actor that receives a message?
你做到了:
val x: Any = ("a", "b")
x match {
case tuple: (Long, DateTime) =>
println("shouldn't match, but does")
}