Scala隐式类嵌套类型参数

时间:2018-01-31 08:42:26

标签: scala implicit-conversion

我有带嵌套类型参数的隐式类,只有在满足某些条件时才为数据对象提供相关方法,并存储类型信息供以后使用。不知何故,嵌套类型参数仅适用于通配符,但不适用于类型参数。我不懂为什么... 以下代码可以使用:

trait A
trait AB extends A
trait AC extends A

trait ByA[T, AX <: A]
case class ByAX[T, AX <: A]() extends ByA[T, AX]
case class Wrapper[T]()

implicit class WithByAB[T](tpe: Wrapper[_ <: ByA[T, AB]]) {
  def printsomething(): Unit = {
    println("WithByAB")
  }
}

Wrapper[ByAX[String, AB]]().printsomething()
//Wrapper[ByAX[String, AC]]().printsomething() does not compile (expected)

这个没有:

trait A
trait AB extends A
trait AC extends A

trait ByA[T, AX <: A]
case class ByAX[T, AX <: A]() extends ByA[T, AX]
case class Wrapper[T]()

implicit class WithByAB[T, S <: ByA[T, AB]](tpe: Wrapper[S]) {
  def printsomething(): Unit = {
    println("WithByAB")
  }
}

Wrapper[ByAX[String, AB]]().printsomething()
//Wrapper[ByAX[String, AC]]().printsomething() does not compile (expected)

看起来编译器无法解析类型T,但如果第一个示例有效并保留参数类型信息,为什么不在第二个示例中?!

1 个答案:

答案 0 :(得分:2)

问题是scala编译器无法推断ByAX[String, AB]实际符合WithByAB[T, S <: ByA[T, AB]]。它无法推断T只与String绑定符合S

我们可以看到使用-Xlog-implicits进行编译时:

λ scalac -Xlog-implicits Implicit.scala
Implicit.scala:22: WithByAB is not a valid implicit value for Wrapper[ByAX[String,AB]] => ?{def printsomething: ?} because:
inferred type arguments [Nothing,ByAX[String,AB]] do not conform to method WithByAB's type parameter bounds [T,S <: ByA[T,AB]]
    Wrapper[ByAX[String, AB]]().printsomething()
                             ^
Implicit.scala:22: error: value printsomething is not a member of Wrapper[ByAX[String,AB]]
    Wrapper[ByAX[String, AB]]().printsomething()
                                ^
one error found

请注意编译器无法从String第一个类型参数中提取ByAX。这是因为从编译器的角度来看,它有S,它由ByAX绑定,但它不知道它的更高阶或它与{{{{}}的内部绑定1}},它可以推断出的只是一种类型,只是String

我们可以通过使S更加详细

来解决这个问题
Wrapper

或者,正如您所指出的那样,将case class Wrapper[T, S]() implicit class WithByAB[T, S <: ByA[T, AB]](tpe: Wrapper[T, S]) { def printsomething(): Unit = { println("WithByAB") } } Wrapper[String, ByAX[String, AB]]().printsomething() 绑定到存在主义。