首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用隐式参数进行隐式转换

使用隐式参数进行隐式转换
EN

Stack Overflow用户
提问于 2012-02-17 18:49:31
回答 2查看 2K关注 0票数 1

我正在实现一个带有许多带有对象参数的方法的Java接口,在我的例子中,这些对象参数实际上是包含用户名的字符串:

代码语言:javascript
复制
public interface TwoFactorAuthProvider {
    boolean requiresTwoFactorAuth(Object principal);
    ... //many more methods with the same kind of parameter
}

在我的实现中,我尝试使用隐式转换将它们转换为User对象:

代码语言:javascript
复制
class TwoFactorAuthProviderImpl(userRepository: UserRepository) 
    extends TwoFactorAuthProvider {

    def requiresTwoFactorAuth(user: User): Boolean = {
        ...
    }
}

当我在我的类的伴生对象中定义转换时,它会被很好地提取,并且我的类会编译:

代码语言:javascript
复制
object TwoFactorAuthProviderImpl {
    implicit def toUser(principal: Any): User = {
        null //TODO: do something useful
    }
}

但是,为了能够进行转换,我需要访问用户存储库,TwoFactorAuthProviderImpl实例拥有该存储库,但伴生对象没有。我想我可以使用隐式参数来传递它:

代码语言:javascript
复制
implicit def toUser(principal: Any)(implicit repo: UserRepository): User = {
    val email = principal.asInstanceOf[String]
    repo.findByEmail(email)
}

但是有了隐式参数,编译器就不再提取转换(抱怨我没有实现接口)。

有没有办法得到我想要的隐式转换,或者这超出了隐式转换的范围?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-02-17 19:21:48

这应该可以很好地工作--你能提供确切的编译错误吗?没有实现什么接口?看起来您必须按如下方式声明:

代码语言:javascript
复制
class TwoFactorAuthProviderImpl(implicit userRepository: UserRepository) 

下面的示例向class X展示了隐式可以有隐式;我使用粘贴模式来确保module X是REPL的伴生对象

代码语言:javascript
复制
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
                  ^

但是如果我们在作用域中添加一个隐式字符串

代码语言:javascript
复制
scala> implicit val s = "Foo"
s: java.lang.String = Foo

scala> val i: X = 4
i: X = X(4,Foo)

隐含的建议

不要过度使用隐式转换-我认为从这个意义上说你走得太远了-主体是一种隐含的机制,通过它你可以发现用户,而不是隐含的用户本身。我很想做这样的事情:

代码语言:javascript
复制
implicit def Principal_Is_UserDiscoverable(p: String) = new {
  def findUser(implicit repo: UserRepository) = repo.findUser(p)
}

然后就可以执行"oxbow".findUser

票数 4
EN

Stack Overflow用户

发布于 2012-02-17 20:04:32

多亏了Oxbow's answer,我现在可以让它工作了,这只是一个参考。

首先,应该作为隐式传递的值本身必须标记为隐式:

代码语言:javascript
复制
class TwoFactorAuthProviderImpl(implicit userRepository: UserRepository) ...

其次,隐式转换很好,但方法实现签名必须与其声明的签名相匹配。因此,即使存在从AnyUser的转换,这也不会编译

代码语言:javascript
复制
def requiresTwoFactorAuth(principal: User): Boolean = { ... }

但是,将参数保留为Any,就像在声明中一样,然后作为用户使用它就可以了:

代码语言:javascript
复制
def requiresTwoFactorAuth(principal: Any): Boolean = {
    principal.getSettings().getPhoneUsedForTwoFactorAuthentication() != null
}

此外,在这种情况下,转换实际上不一定要在伴生对象中,所以最后,我省略了隐式参数。

完整的源代码:

代码语言:javascript
复制
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
    }

    ...
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9326880

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档