对象中无法访问Scala隐式类成员

时间:2017-07-01 11:05:04

标签: scala bcrypt scala-implicits

我使用Scala bCrypt wrapper来加密用户密码,这个包装器提供了一个隐式类。

package object bcrypt {

  implicit class Password(val pswrd: String) extends AnyVal {
    def bcrypt: String = B.hashpw(pswrd, BCrypt.gensalt())

    def bcrypt(rounds: Int): String = B.hashpw(pswrd, BCrypt.gensalt(rounds))

    def bcrypt(salt: String): String = B.hashpw(pswrd, salt)

    def isBcrypted(hash: String): Boolean = B.checkpw(pswrd, hash)
  }

  def generateSalt: String = B.gensalt()
}

但是我遇到一个奇怪的问题,每当我在中使用这个隐式转换时,它工作得很好但是转换不适用于对象案例类< /强>

scala> import com.github.t3hnar.bcrypt._
import com.github.t3hnar.bcrypt._

scala> class Password(secret: String) {
     |   def validate(userSecret: String): Boolean = userSecret.isBcrypted(secret)
     | 
     |   override def toString = secret
     | }
defined class Password

scala> object Password {
     |   def apply(secret: String): Password = new Password(secret)
     | 
     |   def getEncrypted(secret: String) = new Password(secret.bcrypt)
     | }
<console>:18: error: value bcrypt is not a member of String
         def getEncrypted(secret: String) = new Password(secret.bcrypt)
                                                                ^

scala> 

我不确定我在这里做错了什么。

1 个答案:

答案 0 :(得分:3)

任何稳定标识符都会导致导入implicit个标识符。可能影响隐含的内容包括valdefobject以及case class生成的伴随对象。简单的class es和type不会创建标识符,因此不会影响导入的implicit个标识符。

implicit class Password只是class Passwordimplicit def Password的语法糖,因此代码Password中的标识符会隐藏implicit def。< / p>

因此,虽然此代码编译正常:

object Foo {
  import bcrypt._
  class Password()
  "123".bcrypt
}

以下所有代码段都无法编译:

object Foo2 {
  import bcrypt._
  val Password = 1
  "123".bcrypt
}

object Foo3 {
  import bcrypt._
  def Password() = 1
  "123".bcrypt
}

object Foo4 {
  import bcrypt._
  case class Password()
  "123".bcrypt
}

object Foo5 {
  import bcrypt._
  object Password
  "123".bcrypt
}

您的案例中的解决方案很简单:将隐式类重命名为其他类,这不太可能与其他标识符冲突。例如,implicit class PasswordExtensions

如果您无法重命名原始代码中的implicit class,则可以使用其他名称​​导入import com.github.t3hnar.bcrypt.{Password => PasswordExtensions, _}