繁体   English   中英

无法在Scala隐式类中重载apply方法

[英]Can't overload apply method in Scala Implicit class

我正在使用asyncawait编写retry功能

  def awaitRetry[T](times: Int)(block: => Future[T]): Future[T] = async {
    var i = 0
    var result: Try[T] = Failure(new RuntimeException("failure"))

    while (result.isFailure && i < times) {
      result = await { Try(block) } // can't compile
      i += 1
    }

    result.get
  }

Scala编译器报告错误。 由于Try没有应用方法,因此需要使用Future[T] 所以我用隐式类解决了

  implicit class TryCompanionOps(val t: Try.type) extends AnyVal {
    // can't use `apply`!
    def convertTriedFuture[T](f: => Future[T]): Future[Try[T]] = 
      f.map(value => Try(value))
  }  

  // now we can convert Future[T] into Future[Try[T]] e.g,
  await { Try.convertTriedFuture(block) }

我的问题是
为什么不能使用名称apply而不是convertTriedFuture 似乎scala编译器不允许仅重载 隐式类中的 apply方法。

谢谢。

Scala仅在找不到具有所需签名的现有方法时才开始寻找隐式转换。 但是在Try伴随对象中,已经有一个合适的方法: def apply[T](r: ⇒ T): Try[T] ,因此Scala apply T推断为Future[Something] ,并且不检查隐式转换。

另外,此实现将无法正常工作:

def convertTriedFuture[T](f: => Future[T]): Future[Try[T]] = 
  f.map(value => Try(value))

如果Future失败,则不会调用map的函数,并且从await抛出Exception,并且async立即导致失败的Future 因此,使用此实现,该函数实际上不会重试。

您需要类似:

def convertTriedFuture[T](f: => Future[T]): Future[Try[T]] =
  f.map(Success.apply).recover { case e => Failure(e) }

另外,我认为,在期货中定义此恢复方法可能更简洁:

implicit class FutureAdditionalOps[T](f: Future[T]) {
  def recoverError: Future[Try[T]] =
    f.map(Success.apply).recover { case e => Failure(e) }
}

然后你可以

result = await { block.recoverError }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM