我正在实现一个带有许多带有对象参数的方法的Java接口,在我的例子中,这些对象参数实际上是包含用户名的字符串:
public interface TwoFactorAuthProvider {
boolean requiresTwoFactorAuth(Object principal);
... //many more methods with the same kind of parameter
}在我的实现中,我尝试使用隐式转换将它们转换为User对象:
class TwoFactorAuthProviderImpl(userRepository: UserRepository)
extends TwoFactorAuthProvider {
def requiresTwoFactorAuth(user: User): Boolean = {
...
}
}当我在我的类的伴生对象中定义转换时,它会被很好地提取,并且我的类会编译:
object TwoFactorAuthProviderImpl {
implicit def toUser(principal: Any): User = {
null //TODO: do something useful
}
}但是,为了能够进行转换,我需要访问用户存储库,TwoFactorAuthProviderImpl实例拥有该存储库,但伴生对象没有。我想我可以使用隐式参数来传递它:
implicit def toUser(principal: Any)(implicit repo: UserRepository): User = {
val email = principal.asInstanceOf[String]
repo.findByEmail(email)
}但是有了隐式参数,编译器就不再提取转换(抱怨我没有实现接口)。
有没有办法得到我想要的隐式转换,或者这超出了隐式转换的范围?
发布于 2012-02-17 19:21:48
这应该可以很好地工作--你能提供确切的编译错误吗?没有实现什么接口?看起来您必须按如下方式声明:
class TwoFactorAuthProviderImpl(implicit userRepository: UserRepository) 下面的示例向class X展示了隐式可以有隐式;我使用粘贴模式来确保module X是REPL的伴生对象
scala> :paste
// Entering paste mode (ctrl-D to finish)
case class X(i: Int, s: String)
object X { implicit def Int_Is_X(i: Int)(implicit s: String) = X(i, s) }
// Exiting paste mode, now interpreting.
defined class X
defined module X
scala> val i: X = 4
<console>:9: error: value X is not a member of object $iw
val i: X = 4
^但是如果我们在作用域中添加一个隐式字符串
scala> implicit val s = "Foo"
s: java.lang.String = Foo
scala> val i: X = 4
i: X = X(4,Foo)隐含的建议
不要过度使用隐式转换-我认为从这个意义上说你走得太远了-主体是一种隐含的机制,通过它你可以发现用户,而不是隐含的用户本身。我很想做这样的事情:
implicit def Principal_Is_UserDiscoverable(p: String) = new {
def findUser(implicit repo: UserRepository) = repo.findUser(p)
}然后就可以执行"oxbow".findUser了
发布于 2012-02-17 20:04:32
多亏了Oxbow's answer,我现在可以让它工作了,这只是一个参考。
首先,应该作为隐式传递的值本身必须标记为隐式:
class TwoFactorAuthProviderImpl(implicit userRepository: UserRepository) ...其次,隐式转换很好,但方法实现签名必须与其声明的签名相匹配。因此,即使存在从Any到User的转换,这也不会编译
def requiresTwoFactorAuth(principal: User): Boolean = { ... }但是,将参数保留为Any,就像在声明中一样,然后作为用户使用它就可以了:
def requiresTwoFactorAuth(principal: Any): Boolean = {
principal.getSettings().getPhoneUsedForTwoFactorAuthentication() != null
}此外,在这种情况下,转换实际上不一定要在伴生对象中,所以最后,我省略了隐式参数。
完整的源代码:
class TwoFactorAuthProviderImpl(userRepository: UserRepository)
extends TwoFactorAuthProvider {
private implicit def toUser(principal: Any): User = {
val email = principal.asInstanceOf[String]
userRepository.findByEmail(email)
}
def requiresTwoFactorAuth(principal: Any): Boolean = {
//using principal as a User
principal.getSettings().getPhoneUsedForTwoFactorAuthentication() != null
}
...
}https://stackoverflow.com/questions/9326880
复制相似问题