让我们想象我有以下基本特质和案例类
sealed trait BaseTrait
case class Foo(x: Integer = 1) extends BaseTrait
case class Bar(x: String = "abc") extends 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
与匹配案例内的适当基础实例一起调用,这似乎无视以某种通用方式处理它们的全部点 - 使用basemodel和基本处理器中的抽象类型,一只手摆脱了basemodel中有点不需要的类型参数,但编译器的投诉仍然有效,我无法弄清楚是否有可能使它能够工作<</li>
- 从基本模型中摆脱类型的参数和相反,只需在处理器中铸造一个类型以获取适当的类型,但是显式类型的铸造也不是我真正希望的
喜欢:
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])
}
我想一个人也可以以某种方式说服编译器,两种类型(func参数p的T的T和T的T)是等效的,但这似乎也是一个过高的杀伤力(而且我也不确定它如何确定它是如何的可以完成)。
所以我的问题是:是否有可能在这里尝试实现的目标(以统一的方式管理处理器 每个处理器都以某种简单的方式知道其特定类型的基础属性)?我缺少一个更好的模型吗?
更新
根据蒂姆的答案,使控制器隐含地解决了问题,但是,如果您想在一个类中定义控制器 在其接口上具有" 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,一个用于栏):
找不到参数处理器的隐式值:基本处理器[foo]
方法的论点不足
有办法解决吗?我当然可以曝光控制器,以便可以隐式地通过,但是我宁愿不这样做。
您可以通过制作处理器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
,它将在其上调用BarProcessor
。