使用隐式方式以通用方式管理特征实例使用者

时间:2019-01-08 18:18:49

标签: scala generics types implicit

这是previous one的后续问题,这是我当前的示例:

test / package.scala

package object test {
    sealed trait BaseTrait {
        type T <: BaseState
        def state: T
    }
    case class Foo(state: FooState) extends BaseTrait
    case class Bar(state: BarState) extends BaseTrait

    sealed trait BaseState
    case class FooState(f: Integer = 1) extends BaseState
    case class BarState(s: String = "abc") extends BaseState
}

test / base / BaseModel.scala

trait BaseModel[T <: BaseState] {
    var baseVar: Option[T] = None
}

test / base / BaseProcessor.scala

trait BaseProcessor[T <: BaseTrait#T] {
    def model: BaseModel[T]
    def process(x: T): Unit = model.baseVar = Option(x)
}

test / foo / FooProcessor.scala

class FooProcessor(val model: FooModel) extends BaseProcessor[Foo#T] {
    val v: Option[FooState] = model.baseVar
}

test / foo / FooModel.scala

class FooModel extends BaseModel[FooState]

test / bar / BarProcessor.scala

class BarProcessor(val model: BarModel) extends BaseProcessor[Bar#T] {
    val v: Option[BarState] = model.baseVar
}

test / bar / BarModel.scala

class BarModel extends BaseModel[BarState]

test / Test.scala

object Test extends App {
    val test = Test2
    val foo = Foo(FooState())
    val bar = Bar(BarState())

    test.func(foo)
    test.func(bar)
}

test / Test2.scala

class Test2 {
    private implicit val fooProcessor = new FooProcessor(new FooModel)
    private implicit val barProcessor = new BarProcessor(new BarModel)

    def func[T <: BaseTrait](p: T) {
        tfunc(p.state)
    }

    private def tfunc[T <: BaseTrait#T](p: T)(implicit processor: BaseProcessor[T]) {
        processor.process(p)
    }
}

我要实现的目标如下:

  • 不要将Test2内部存在的各种处理器暴露给外界,因此应该处理所有隐式业务的“正常”功能和“类型化” tfunc
  • 能够使用/访问每个BaseEditor专业化内的正确类型化的状态(即model.baseVar应该始终是正确的类型)
  • 以通用方式处理处理器,以便tfunc尽可能简单,并且不需要类型转换/模式匹配

如果我尝试运行当前所拥有的内容,则会出现以下编译器错误:

  

找不到参数处理器的隐式值:   base.BaseProcessor [p.T]

我不太了解的

,因为tfunc都期望T <: BaseTrait#T,而隐式处理器也具有相同的type参数,所以我希望编译器将它们匹配。

请注意,如果我将BaseTrait中的抽象类型更改为type T = BaseTrait,则所有隐式函数似乎都与tfunc的预期类型匹配,因此我得到了

  

含糊的隐式值

编译器错误。在我看来,由于某种原因,编译器并没有真正正确地获得这些上限,但是我的假设可能是错误的。另外,如果我将tfunc更改为上下文绑定,并尝试通过implicitly[BaseProcessor[T]](或implicitly[BaseProcessor[p.T]],其中p为BaseTrait的上限)召唤适当的处理器,我将得到完全相同的结果。

我在这里错过了明显的东西吗,还是有另一种方法可以实现我在这里想要做的事情?

0 个答案:

没有答案