为什么我需要一个额外的asInstanceOf

时间:2018-05-03 22:47:34

标签: scala

我写了这段代码

listOfClassNames.map{ className => 
  Try {
    GuiceInjector.getInstance(Class.forName(className)).asInstanceOf[BaseClass]
  } recover {
    case _ => Option.empty[(String, BaseClass)]
  } match {
    case Success(bc) => Some((className, bc))
    case _ => Option.empty[(String, BaseClass)]
  }
}

上面的代码会抛出错误

type mismatch;
[error]  found   : List[Option[(String, Object)]]
[error]  required: List[Option[(String, BaseClass)]]

现在,如果我将代码更改为

listOfClassNames.map{ className => 
  Try {
    GuiceInjector.getInstance(Class.forName(className)).asInstanceOf[BaseClass]
  } recover {
    case _ => Option.empty[(String, BaseClass)]
  } match {
    case Success(bc) => Some((className, bc.asInstanceOf[BaseClass]))
    case _ => Option.empty[(String, BaseClass)]
  }
}

现在它有效。但根据我的说法,第二个asInstanceOf是不必要的,因为第一个对象本身就是类型转换。没有?

1 个答案:

答案 0 :(得分:3)

您必须删除对recover的通话。无论如何都不需要它,因为你在match中处理错误案例,但它会弄乱代码的类型和正确性。

考虑类型:Try { /* ... */.asInstanceOf[BaseClass] } 类型为Try[BaseClass]

然后Try { /* ... */ } recover { case _ => Option.empty[(String, BaseClass)] }TryBaseClass的常见超类型的Option[(String, BaseClass)],因此它是Try[AnyRef]

因此,在case Success(bc) =>的匹配内,此bc具有类型AnyRef,并且在运行时,它可以是BaseClassNone的实例。如果来自Guice的原始抓取BaseClass失败,则此bcNone,并且您获得ClassCastException的附加isInstanceOf