尝试使用隐式类扩展它时,代表扩展方法不可用?

问题描述

我正在尝试使用通过 Scala 的 Rep 作为扩展方法提供的新方法 =?= 来扩展 Slick implicit class

import slick.ast.TypedType
import slick.lifted.LiteralColumn
import slick.lifted.Rep

object RepExtensions {
  implicit class RichRep[T](rep: Rep[T]) {
    def =?=(rhs: Option[T])(implicit tt: TypedType[Boolean]): Rep[Boolean] =
      rhs.map(rep === _).getorElse(LiteralColumn[Boolean](true))
  }
}

但是在这种情况下,由于我无法确定的原因,方法 === 对编译器不可见:

[error] /Users/.../RepExtensions.scala:10:19: value === is not a member of slick.lifted.Rep[T]
[error]       rhs.map(rep === _).getorElse(LiteralColumn[Boolean](true))
[error]

=== 方法在 Slick 的 ColumnExtensionMethods 中定义,但我找不到任何解释如何将其显式导入作用域的文档 - 直接导入该类本身当然无济于事。实际上,在我处理 Rep 类型的其余代码中,=== 方法似乎可以在我需要时免费使用,无需任何特殊努力或显式导入。

在这种情况下,如何将 === 方法纳入范围?

解决方法

扩展方法是通过 ExtensionMethodConversions 中的隐式定义为类型实现的(参见 ExtensionMethods.scala 的底部)。这意味着,要使 === 可用,隐式需要应用于您的类型 T。由于 T 不受约束,因此它不匹配任何将 === 带入作用域的隐式定义。

解决此问题的一种方法是将 T 限制为匹配。例如:

import slick.ast.BaseTypedType
import slick.jdbc.H2Profile.api._ // or whichever database you use

object RepExtensions {
  implicit class RichRep[T : BaseTypedType](rep: Rep[T]) {
    def =?=(rhs: Option[T]): Rep[Boolean] =
      rhs.map(rep === _).getOrElse(LiteralColumn[Boolean](true))
  }
}

下一步是需要一个 Shape,如下所述:https://stackoverflow.com/a/43014901/154248 -- 但看起来您不需要这个定义。