Scala 隐式 class 成员在对象中不可访问
Scala Implicit class member is not accessible in object
我正在使用 Scala bCrypt wrapper 来加密用户密码,这个包装器提供了一个隐式 class.
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()
}
但我面临一个奇怪的问题,每当我在 class 中使用此隐式转换时,它工作正常但转换不适用于 object 或 case classes.
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>
我不确定我做错了什么。
任何稳定的标识符都会影响导入的 implicit
标识符。可以隐藏隐式的东西包括 val
、def
、object
和 case class
的生成伴随对象。简单的 class
es 和 type
s 不会创建标识符,因此不会隐藏导入的 implicit
标识符。
implicit class Password
只是 class Password
和 implicit def Password
的语法糖,因此代码中名为 Password
的标识符会隐藏 implicit def
.
因此,当此代码编译正常时:
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
}
您的解决方案很简单:将隐式 class 重命名为其他名称,这样不太可能与其他标识符发生冲突。例如,implicit class PasswordExtensions
。
如果你不能重命名原代码中的implicit class
,你可以导入它在一个不同的名字下:import com.github.t3hnar.bcrypt.{Password => PasswordExtensions, _}
我正在使用 Scala bCrypt wrapper 来加密用户密码,这个包装器提供了一个隐式 class.
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()
}
但我面临一个奇怪的问题,每当我在 class 中使用此隐式转换时,它工作正常但转换不适用于 object 或 case classes.
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>
我不确定我做错了什么。
任何稳定的标识符都会影响导入的 implicit
标识符。可以隐藏隐式的东西包括 val
、def
、object
和 case class
的生成伴随对象。简单的 class
es 和 type
s 不会创建标识符,因此不会隐藏导入的 implicit
标识符。
implicit class Password
只是 class Password
和 implicit def Password
的语法糖,因此代码中名为 Password
的标识符会隐藏 implicit def
.
因此,当此代码编译正常时:
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
}
您的解决方案很简单:将隐式 class 重命名为其他名称,这样不太可能与其他标识符发生冲突。例如,implicit class PasswordExtensions
。
如果你不能重命名原代码中的implicit class
,你可以导入它在一个不同的名字下:import com.github.t3hnar.bcrypt.{Password => PasswordExtensions, _}