【问题标题】:testing if a given instance is a (sub)class of a given Class in scala测试给定实例是否是scala中给定类的(子)类
【发布时间】:2012-09-27 09:20:35
【问题描述】:

说给定一个List[Class[_ <: Base]] 的实例,并说许多类扩展了Base

class A extends Base
class B extends Base
class C extends A

等等……
现在,给定的列表可能只包含一些类。例如:val classes = classOf[A] :: Nil,好吧,当我得到一个实例化的val 时,我如何测试它的类是否属于列表中的类型,或者它是否是列表中某个类的子类?即你将如何实现:
def testClass(class : List[Class[_ <: Base]], instance : Base) : Boolean
什么时候:

val classes = classOf[A] :: Nil
testClass(classes, new A) // should return true
testClass(classes, new B) // should return false
testClass(classes, new C) // should return true

用例:
我正在尝试编写一个通用的重试模式,即获取一些非常容易出错的代码,并且我想重试执行它的最大尝试次数,当每次失败时,它应该执行一些“等待”方法。
例如

retryRequest({
    //Some code that throws exceptions
}, classOf[SomeException] :: classOf[SomeOtherException] :: Nil,
100, {Thread.sleep(5000)})

这工作正常,但它不会测试给定异常的子类:

def retryRequest(req : => Unit, validExceptions : List[Class[_ <: java.lang.Throwable]], tries : Int, waitMethod : => Unit) {
    var keepTrying = false
    var tryCount = 0
    do{
        try{
            logger.debug("retryRequest, try #" + tryCount)
            keepTrying = false
            req
        }catch{
            case ex if(tryCount >= tries && validExceptions.contains(ex.getClass)) => {
                throw new MaxTriesReachedException("tried for " + tryCount + "times, but no luck. " +
                                                   "you may want to try ommitting generic exceptions types from the given list.") 
            }
            case ex if (validExceptions.contains(ex.getClass)) => {
                logger.debug("intercepted " + ex.toString)
                tryCount += 1
                keepTrying = true
                waitMethod
            }
        }
    }while(keepTrying)
}

我真的很想替换:

validExceptions.contains(ex.getClass)

类似:

validExceptions.exists(exClass => ex.isInstanceOf[exClass]) //won't compile

有可能吗?怎么样?

【问题讨论】:

标签: scala types


【解决方案1】:

更简单的方法是使用util.control.Exception:

  def retryRequest(req: => Unit, 
                   validExceptions: List[Class[_ <: Throwable]], 
                   tries: Int, 
                   waitMethod: => Unit): Unit =
   (Exception.catching(validExceptions:_*) withApply { e => 
      waitMethod
      if (tries > 1) retryRequest(req, validExceptions, tries - 1, waitMethod)
   }) { req }

  retryRequest( { println("a"); throw new Exception }, 
                List(classOf[Exception]), 
                3,
                Thread.sleep(100))

简而言之:withApply 采用一个闭包来处理传递给catching 的异常之一被抛出时的情况。在我们的例子中,我们只是递归地调用自己(鉴于重试次数很少,我认为这不是问题)。

【讨论】:

    【解决方案2】:

    我认为这应该可行:

    validExceptions.exists(exClass => exClass.isAssignableFrom(ex.getClass))
    

    http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#isAssignableFrom%28java.lang.Class%29

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-26
      • 1970-01-01
      • 1970-01-01
      • 2017-12-06
      • 1970-01-01
      • 2012-06-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多