1

宣言されたいくつかの例外を再試行するが、他の例外をスローする制御構造を開発しようとしています。制御構造はうまく機能しますが、キャッチされた例外が宣言された例外のタイプに属しているかどうかを確認するのに問題があります。より一般的な言葉で言えば、パラメーターが型パラメーターの宣言されたリストの 1 つであるかどうかを確認するにはどうすればよいですか?

再試行制御構造を定義します。

def retry[T, R](times:Int=3, delay:Int=1000)(ex:Class[_<:Exception]*)(t:T)(block:T=>R):R = {
try {
  block(t)
}
catch {
  case e:Exception if (isOneOf(e, ex:_*) && times>0) => {
    println(s"Exception $e happened, sleep $delay milliseconds")
    Thread.sleep(delay)
    println(s"$times times remain for retry before give up")
    retry(times-1, delay)(ex:_*)(t)(block)
  }
  case e:Throwable => {
    println(s"Exception $e is not handled")
    throw e
  }
}

}

isOneOf 関数を定義して、宣言されたランタイム例外タイプをチェックします

def isOneOf[T:scala.reflect.ClassTag](obj:T, cs:Class[_]*) = {
  val dc = obj.getClass
  val rc = scala.reflect.classTag[T].runtimeClass
  cs.exists(c=>c.isAssignableFrom(dc) || c.isAssignableFrom(rc))
}

複数の例外をスローする関数を定義する

def d(str:String) = {
  val r = Math.random()
  println(r)

  if (r>0.6) throw new IllegalArgumentException
  else if (r>0.4) throw new java.io.IOException
  else if (r>0.2) throw new UnsupportedOperationException
  else println(str)
}

そして、次のように再試行して関数を呼び出すことができます。

retry(3, 1000)(classOf[IllegalArgumentException], classOf[java.io.IOException])("abc"){
  x=> d(x)
}

IllegalArgumentException と IOException で再試行したいのですが、UnsupportedOperationException がスローされます。

私の目標は、次のように関数を呼び出すことです。

retry(3, 1000)[IllegalArgumentException, java.io.IOException]("abc"){
  x=> d(x)
}

再試行構造の場合、宣言された例外のリストが実行時に動的に渡されます。したがって、複数の例外ケースステートメントは機能しません。例外がキャッチされたら、一般的な例外と照合し、isOneOf 関数で例外の種類を確認します。理想的には、関数は一連のクラスではなく一連の型を取ります。クラスのシーケンスではなく、例外タイプのシーケンスを渡し、キャッチされた例外をタイプのシーケンスに対してチェックするにはどうすればよいですか?

4

1 に答える 1

2

例外のリストを、どの例外が回復可能か (そしてどれが動的に構築できるか) を知る関数に置き換えることについてどう思いますか?

def retry[T, R](times: Int = 3, delay: Int = 1000)(t: T)(block: T => R)(recoverable: Throwable => Boolean): R = {

  Try(block(t)) match {
    case Success(value) => value
    case Failure(throwable) => if (recoverable(throwable)) retry(times - 1, delay)(t)(block)(recoverable) else throw throwable
  }

}

recoverable関数は次のようになります。

def recoverable(throwable: Throwable): Boolean = throwable match {
  case exc @ (_: IllegalArgumentException | _: IOException) => true
  case _ => false
}
于 2013-12-20T15:17:07.400 に答える