以下是我想要做的简短示例:
abstract class Message()
case class FooMessage() extends Message
case class BarMessage() extends Message
//... other messages ...
trait Component
{
def handleMessage(msg: Message):Unit
}
trait ComponentType1 extends Component
{
abstract override def handleMessage(msg: FooMessage) = {
//handle foo, pass it up the chain
super.handleMessage(msg)
}
abstract override def handleMessage(msg: BarMessage) = {
//handle bar, pass it up the chain
super.handleMessage(msg)
}
}
//handles some other messages, also might handle the same messages as ComponentType1
trait ComponentType2 extends Component { .. }
然后,这些ComponentType
在中混合到一个类中,形成一个完全由模块化组件组成的对象。
我有一堆不同的Message
和一堆不同的Component
。
问题在于,handleMessage
在Component
中定义为接受Message
,当我尝试专门化msg
参数时,它不算作覆盖。
我知道一个可能的解决方案是使用大匹配语句声明一个大的handleMessage
方法,但是如果可能的话,我想为每条消息定义一个方法。
答案 0 :(得分:3)
这是基于部分功能的解决方案。向CheatEx提示这个想法。
trait Message
class FooMessage extends Message
class BarMessage extends Message
abstract class Component {
type CPF = PartialFunction[Message, Unit]
var pf: CPF = { case _ => }
def handleMessage(msg: Message) = pf(msg)
}
trait ComponentType1 extends Component {
val ct1pf: CPF = {
case msg: FooMessage => println("foo1")
case msg: BarMessage => println("bar1")
}
pf = ct1pf orElse pf
}
trait ComponentType2 extends Component {
val parentPf = pf
val ct2pf: CPF = {
case msg:
BarMessage => println("bar2")
parentPf(msg) // cascade
}
pf = ct2pf orElse pf
}
object component1and2 extends ComponentType1 with ComponentType2
component1and2.handleMessage(new FooMessage)
component1and2.handleMessage(new BarMessage)
打印
foo1
bar2
bar1
答案 1 :(得分:1)
trait Message
class FooMessage extends Message
class BarMessage extends Message
trait Component {
def handleMessage(msg: Message) {}
def handleMessage(msg: FooMessage) {}
def handleMessage(msg: BarMessage) {}
}
trait ComponentType1 extends Component {
override def handleMessage(msg: FooMessage) = println("foo1")
override def handleMessage(msg: BarMessage) = println("bar1")
}
trait ComponentType2 extends Component {
override def handleMessage(msg: BarMessage) = println("bar2")
}
object component1and2 extends ComponentType1 with ComponentType2
component1and2.handleMessage(new FooMessage)
component1and2.handleMessage(new BarMessage)
打印
foo1
bar2
如果您在系统中的所有组件的某个位置有一个列表,那么
componentList.foreach(c => c.handleMessage(msg))
对于没有处理msg的组件,它只会在Component中无操作。
答案 2 :(得分:0)
为了完整性:
trait Message
class FooMessage extends Message
class BarMessage extends Message
trait Component {
def handleMessage(msg: Message) {}
}
trait ComponentType1 extends Component {
def handleMessage(msg: Message) {
msg match {
case m: FooMessage => println("foo1")
case m: BarMessage => println("bar1")
case _ => super.handleMessage(msg)
}
}
}
trait ComponentType2 extends Component {
override def handleMessage(msg: Message) {
msg match {
case m: BarMessage =>
println("bar2")
super.handleMessage(m) // cascade
case _ => super.handleMessage(msg)
}
}
}
object component1and2 extends ComponentType1 with ComponentType2
component1and2.handleMessage(new FooMessage)
component1and2.handleMessage(new BarMessage)
打印
foo
bar2
bar1