【问题标题】:In Scala, is there a way to have two overloaded methods that only differ in whether an implicit is available?在 Scala 中,有没有办法让两个重载方法仅在隐式是否可用方面有所不同?
【发布时间】:2012-07-19 02:03:21
【问题描述】:

我正在编写一个访问数据库的 Scala 应用程序。大多数时候,会有可用的连接,但有时不会。我想做的是如下所示:

object User {
  def authenticate(username: String, password: String)
      (implicit conn: Connection): Option[User] = {
    // use conn to grab user from db and check that password matches
    // return Some(user) if so, None if not
  }
  def authenticate(username: String, password: String): Option[User] = {
    implicit val conn = DB.getConnection()
    authenticate(username, password)
  }
}

我希望发生的是,如果有一个 Connection 类型的隐式值可用,编译器将使用第一种方法。如果没有,它将使用第二个。不幸的是,我发现编译器并不那么聪明,或者,如果是的话,我并没有告诉它以正确的方式做什么。

所以,我的基本问题是,有没有一种方法可以编写一个需要隐式参数的方法,然后提供相同方法的重载版本,如果没有可用的隐式参数类型创建可接受的值.

您可能会说,“您为什么要做这样的事情?如果您可以创建适当类型的可接受值,为什么不总是这样做呢?”这基本上是正确的,除了如果我有一个开放的数据库连接,我宁愿继续使用它而不是创建一个新的连接。但是,如果我没有打开的数据库连接,我知道在哪里可以找到。

我的意思是,简单的答案就是给这两种方法起不同的名字,但我不应该这样做,gosh-darn-it。但也许我会...

谢谢! 托德

【问题讨论】:

  • 如何将连接包装在某个负责调用getConnection 和存储的类中?那么你只需要一种方法将这个新类作为隐式。

标签: scala overloading


【解决方案1】:

您不需要重载方法。只需给你的隐式参数一个默认值,即

object User {
  def authenticate(username:String, password:String)(implicit conn:Connection = null): Option[User] = {
    val real_conn = Option(conn).getOrElse(DB.getConnection())
    // do the rest with the real_conn
  }
}

【讨论】:

  • 为什么不隐式 conn:Option[Connection] ?
  • conn 如果您不在范围内提供隐式值,则将为 null,否则它将采用该值。当然你可以使用 Option[Connection] 但这需要你修改你的上下文代码,这可能是很多变化。
  • @pedrofurla:我第一次看到的时候也想知道这个,但是it's legit:“如果参数有默认参数并且找不到隐式参数,则使用默认参数。”
  • 哦,哦,对不起,我没有看到默认参数。我的错。删除评论。
  • 现在为什么我没有想到呢?谢谢!
【解决方案2】:

我能想到的更简洁的解决方案是使用嵌套方法,正如有人建议的那样,隐式的默认值。

class Testclass {

  def myMethod(a:Int)(implicit b:Option[Int]=None):Int = {

    def myMethodInternal(a:Int, b:Int):Int = {
      // do something
      a+b
    }
    val toUse = b.getOrElse(30)
    myMethodInternal(a,toUse)
  }
}

在您的方法中定义一个 myMethodInternal,它不接受隐式参数,而只接受显式参数。此方法仅在 myMethod 中可见,您将准备第二个参数,如下所示:

  val toUse = b.getOrElse(30)

最后用显式参数调用你的方法:

  myMethodInternal(a,toUse)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-24
    • 2012-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多