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$1$StringHandler.handle(typeProblem.scala:11)
at Main$$anon$1$Handler.handleAny(typeProblem.scala:5)
如何更改代码段(不更改界面或用类型参数替换类型字段)按预期工作,仅处理由类型字段指定的消息 ?
我正在寻找一种可以应用于父抽象类而不是污染所有孩子的解决方案。
我还尝试使用match
,它的行为完全相同。或者类型字段是不可能的(我认为它们比类型参数更强大)?
答案 0 :(得分:2)
通常使用匹配,在您的情况下,因为您不想添加任何类型参数,您必须指定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)