簡體   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