我可以使用返回this.type的方法在参数化特征上“Pimp my Library”吗?

时间:2016-07-04 10:05:13

标签: scala implicit-conversion builder implicit extending

我希望使用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很重要,不能忽略。

1 个答案:

答案 0 :(得分:2)

在变体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在每个类都可用,所以即使编译器推断{{1},也不是一个好的测试代码将编译):

Any