假设我具有以下基本特征和案例类
sealed trait BaseTrait
case class Foo(x: Integer = 1) extends BaseTrait
case class Bar(x: String = "abc") extends BaseTrait
我想为可以处理BaseTrait实例的类创建一个通用接口,如下所示:
class FooProcessor(val model: FooModel) extends BaseProcessor[Foo] {
val v: Option[Foo] = model.baseVar
}
class BarProcessor(val model: BarModel) extends BaseProcessor[Bar] {
val v: Option[Bar] = model.baseVar
}
为此,我具有以下特征
trait BaseModel[T <: BaseTrait] {
var baseVar: Option[T] = None
}
trait BaseProcessor[T <: BaseTrait] {
def model: BaseModel[T]
def process(x: T): Unit = model.baseVar = Option(x)
}
模型定义如下
class FooModel extends BaseModel[Foo]
class BarModel extends BaseModel[Bar]
现在让我们想象一下我的应用程序中有以下处理器
val fooProcessor = new FooProcessor(new FooModel)
val barProcessor = new BarProcessor(new BarModel)
我想以某种通用的方式来处理它们,
def func[T <: BaseTrait](p: T) {
val c/*: BaseProcessor[_ >: Foo with Bar <: BaseTrait with Product with Serializable]*/ = p match {
case _: Foo => fooProcessor
case _: Bar => barProcessor
c.process(p)
}
编译器对最后一行并不满意
类型不匹配;
找到:T
必填:_1
如果我正确理解,那基本上是编译器试图阻止barProcessor.process(Foo())
发生。我尝试了几种解决方案来解决此问题并实现所需的行为:
*Processor.process
,这似乎无济于事。
像这样:
trait BaseModel {
var baseVar: Option[BaseTrait] = None
}
trait BaseProcessor[T <: BaseTrait] {
def model: BaseModel
def process(x: T): Unit = model.baseVar = Some(x)
def getBaseValue: T = model.baseVar.map(_.asInstanceOf[T])
}
我想有人还可以某种方式说服编译器,这两种类型(Processor的T和func参数p的T)是等效的,但这似乎有点过头了(而且我也不太确定如何可以完成)。
所以我的问题是:是否可以以某种简单的方式来完成我在这里想要实现的目标(以统一的方式管理处理器+每个处理器都知道其特定的BaseTrait类型)?有没有我所缺少的更好的模型?
按照Tim's answer,使控制器隐式解决了问题,但是,如果您想拥有一个定义控制器的类,并且在其接口上具有“ func”,则编译器似乎不再能够正确解析隐式了。所以,如果我尝试做这样的事情
class ProcessorContainer {
implicit val fooProcessor = new FooProcessor(new FooModel)
implicit val barProcessor = new BarProcessor(new BarModel)
def func[T <: BaseTrait](p: T) = typedFunc(p)
private def typedFunc[T <: BaseTrait](p: T)(implicit processor: BaseProcessor[T]) =
processor.process(p)
}
class Test {
val processorContainer = new ProcessorContainer
processorContainer.func(Foo())
processorContainer.func(Bar())
}
我收到以下编译错误(一个用于Foo,一个用于Bar):
找不到参数处理器的隐式值:BaseProcessor [Foo]
方法的参数不足
有没有解决的办法?我当然可以公开控制器,以便可以隐式传递它们,但是我不希望这样做。
答案 0 :(得分:2)
您可以通过使处理器implicit
并将其作为附加参数传递给func
来创建简单的类型类:
implicit val fooProcessor = new FooProcessor(new FooModel)
implicit val barProcessor = new BarProcessor(new BarModel)
def func[T <: BaseTrait](p: T)(implicit processor: BaseProcessor[T]) =
processor.process(p)
如果您将Foo
传递给func
,它将在其上调用FooProcessor.process
,如果您将Bar
传递给func
,它将将调用{{ 1}}。