我可以 "Pimp my Library" 参数化特征,方法返回 this.type 吗?

Can I "Pimp my Library" on a parameterized trait with method returning this.type?

我想使用 Pimp my Library 模式扩展我的 参数化 特征 Field[T],方法返回 this.type。但我坚持编译器错误。我尝试了一些变体,但没有成功。

我做错了吗?还是问不可能的事?

这是我的测试示例:

trait Field[T]

class IntField extends Field[Int] {
  def getInt = 5
}

// Variant 1: return field.type
object Var1 {
  implicit class RichField[T](val field: Field[T]) {
    def bar(fn: T => String): field.type = {
      // some actions using T
      field
    }
  }

  new IntField().bar(_.toString).getInt  // Error: value getInt is not a member of Field[Int]
}

// Variant 2: use two type parameters
object Var2 {
  implicit class RichField[T, F <: Field[T]](val field: F) {
    def bar(fn: T => String): F = {
      // some actions using T
      field
    }
  }

  new IntField().bar(_.toString).getInt // <-- Error: value bar is not a member of IntField
}

// Variant 3: use higher kinds
object Var3 {
  import scala.language.higherKinds

  implicit class RichField[F[X] <: Field[X], T](val field: F[T]) {
    def bar(fn: T => String): F[T] = {
      // some actions using T
      field
    }
  }

  new IntField().bar(_.toString).getInt // <-- Error: value getInt is not a member of Field[Int]
}

更新:参数T对方法bar很重要,不能忽略。

在变体 2 中,您没有在任何地方使用 T。把它去掉,编译器就不会再混淆了:

implicit class RichField[F <: Field[_]](val field: F) {
  def bar: F = field
}

更新:如果您确实需要 T,正如您在评论中提到的,可能的解决方法是:

implicit class RichField[T, F <: Field[_]](val field: F with Field[T]) {
  def bar(fn: T => String): F = {
    // some actions using T
    field
  }
}

这是一个证明它按预期工作的证明(在你的例子中使用 toString 并不是一个好的测试,因为 toString 在每个 class 上可用,所以即使编译器推断 Any 代码会被编译):

scala> case class Foo(name: String)
defined class Foo

scala> class FooField extends Field[Foo] {
     |   def getInt = 5
     | }
defined class FooField

scala> new FooField().bar(_.name).getInt
res8: Int = 5