我昨天开始学习Scala,所以我对它很陌生。在学习新语言时,我喜欢做的一件事是尝试创建一个微型TDD库。
这是我到目前为止所得到的:
def assert(condition: Boolean, message: String) {
if(!condition){ throw new AssertionError(message) }
}
def assertThrows[E](f: => Unit) {
try {
f
} catch {
case e: E => { return }
case _: Exception => { }
}
throw new AssertionError("Expected error of type " + classOf[E] )
}
assert
的代码运行正常,但我遇到了assertThrows
的两个问题。
E
。无论我做什么,我都会得到class type expected but E found error
。throw new AssertionError("error expected")
),我会得到:warning: abstract type E in type pattern is unchecked since it is eliminated by erasure
我认为我遇到的两个问题与Scala(可能是java)处理抽象类型的方式有关,以及它们是如何完成的。
如何修复我的assertThrows?
奖励积分:我指定“块类型”(f: => Unit
)的方式是正确的吗?
答案 0 :(得分:8)
Java虚拟机通过类型擦除实现泛型,因此在方法体内,JVM实际上并不知道E的类型,因此AssertThrows方法无法按照您的方式工作。您需要为异常类隐式传递Manifest,如下所示:
def assertThrows[E](f: => Unit)(implicit eType:ClassManifest[E]) {
然后你可以在正文中使用它来捕获异常或获取类名:
try {
f
} catch {
case e: Exception =>
if ( eType.erasure.isAssignableFrom(e.getClass))
return;
}
throw new AssertionError("Expected error of type " + eType.erasure.getName )
}
感谢the Spring framework's AssertThrows class告诉我如何执行此操作。
答案 1 :(得分:0)
感谢Ken的回答,我得到了这件事:
class AssertException(msg: String) extends Exception(msg: String)
def assertThrows[E](f: => Unit)(implicit eType:ClassManifest[E]) {
try{
f
} catch {
case e: Exception =>
if(eType.erasure.isAssignableFrom(e.getClass)) { return }
}
throw new AssertException("Expected error of type " + eType.erasure.getName )
}
/* examples of usage */
assertThrows[NullPointerException]{ throw new NullPointerException() } // ok
assertThrows[AssertException] { assertThrows[Exception]{ } } // ok!
非常感谢!