擦除类型字段
Erasure of type fields
abstract class Handler {
type Message
def handleAny(msg: Any) {
if (msg.isInstanceOf[Message]) handle(msg.asInstanceOf[Message]) // fix me!
}
def handle(msg: Message)
}
class StringHandler extends Handler {
override type Message = String
def handle(msg: Message) { println(s"handling: $msg") }
}
val h = new StringHandler
h.handleAny("ahoj")
h.handleAny(true)
warning: abstract type Handler.this.Message is unchecked since it is
eliminated by erasure
if(msg.isInstanceOf[Message]) handle(msg.asInstanceOf[Message])
^
one warning found
handling: ahoj
java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.lang.String
at Main$$anon$StringHandler.handle(typeProblem.scala:11)
at Main$$anon$Handler.handleAny(typeProblem.scala:5)
如何更改代码段(不更改接口或用类型参数替换类型字段)以按预期工作,即仅处理由指定的消息类型字段?
我正在寻找一种可以应用于父摘要 class 而不是污染所有子级的解决方案。
我也尝试使用 match
并且它的行为完全相同。还是类型字段不可能实现这种事情(我认为它们比类型参数更强大)?
通常使用匹配,在您的情况下,由于您不想添加任何类型参数,因此您必须指定 ClassTag
(我认为)。
大致如下:
import scala.reflect.ClassTag
abstract class Handler {
type Message <: Any
implicit val tag: ClassTag[Message]
def handleAny(msg: Any): Unit = {
msg match {
case tag(message) =>
handle(message)
case _ =>
throw new IllegalArgumentException(s"Argmument MUST BE a 'Message' but $msg is not!")
}
}
def handle(msg: Message): Unit
}
object StringHandler extends Handler {
override type Message = String
// lazy is important here!
implicit lazy val tag: ClassTag[Message] = ClassTag(classOf[String])
def handle(msg: Message): Unit = { println(s"handling: $msg") }
}
StringHandler.handleAny("ahoj")
StringHandler.handleAny(true)
abstract class Handler {
type Message
def handleAny(msg: Any) {
if (msg.isInstanceOf[Message]) handle(msg.asInstanceOf[Message]) // fix me!
}
def handle(msg: Message)
}
class StringHandler extends Handler {
override type Message = String
def handle(msg: Message) { println(s"handling: $msg") }
}
val h = new StringHandler
h.handleAny("ahoj")
h.handleAny(true)
warning: abstract type Handler.this.Message is unchecked since it is
eliminated by erasure
if(msg.isInstanceOf[Message]) handle(msg.asInstanceOf[Message])
^
one warning found
handling: ahoj
java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.lang.String
at Main$$anon$StringHandler.handle(typeProblem.scala:11)
at Main$$anon$Handler.handleAny(typeProblem.scala:5)
如何更改代码段(不更改接口或用类型参数替换类型字段)以按预期工作,即仅处理由指定的消息类型字段?
我正在寻找一种可以应用于父摘要 class 而不是污染所有子级的解决方案。
我也尝试使用 match
并且它的行为完全相同。还是类型字段不可能实现这种事情(我认为它们比类型参数更强大)?
通常使用匹配,在您的情况下,由于您不想添加任何类型参数,因此您必须指定 ClassTag
(我认为)。
大致如下:
import scala.reflect.ClassTag
abstract class Handler {
type Message <: Any
implicit val tag: ClassTag[Message]
def handleAny(msg: Any): Unit = {
msg match {
case tag(message) =>
handle(message)
case _ =>
throw new IllegalArgumentException(s"Argmument MUST BE a 'Message' but $msg is not!")
}
}
def handle(msg: Message): Unit
}
object StringHandler extends Handler {
override type Message = String
// lazy is important here!
implicit lazy val tag: ClassTag[Message] = ClassTag(classOf[String])
def handle(msg: Message): Unit = { println(s"handling: $msg") }
}
StringHandler.handleAny("ahoj")
StringHandler.handleAny(true)