Член класса Scala Implicit недоступен в объекте
Я использую оболочку Scala bCrypt для шифрования пароля пользователя, эта оболочка предоставляет неявный класс.
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()
}
Но я сталкиваюсь со странной проблемой: всякий раз, когда я использую это неявное преобразование в классе, оно работает нормально, но Converiosn не работает с объектными или тематическими классами.
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 ответ
Любые стабильные идентификаторы импортируются implicit
идентификаторы. Вещи, которые могут скрыть последствия включают val
, def
, object
и сгенерированный сопутствующий объект case class
, просто class
эс и 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
}
Решение в вашем случае простое: переименуйте неявный класс в другое, что вряд ли будет конфликтовать с другими идентификаторами. Например, implicit class PasswordExtensions
,
Если вы не можете переименовать implicit class
в исходном коде вы можете импортировать его под другим именем: import com.github.t3hnar.bcrypt.{Password => PasswordExtensions, _}