mjk*_*mjk 0 generics casting scala traits
我有一个用于 DAO 目的的伪通用类工厂。操作模型非常简单:
1) 使用特定 DAO 对象“T”类型的知识实例化工厂
2) 然后创建 T 的内部实例
3) 它应该调用T的 trait-contracted 函数
4) 最后, 返回 T 的实例(假设一切顺利)
它看起来像这样:
class DAOFactory[T](implicit m: Manifest[T]) {
def obj = m.runtimeClass.asInstanceOf[Class[T]]
def doFoo(): Option[Any] = {
val dao = obj.asInstanceOf[DAO] // (A) this line will crash
println(obj.toString()) // some.object.called.DAOTodo
// val bar = dao.doSomethingSmart(now) <--- ALL DAO-derived classes implement this function
return Some(obj) // error-catching excluded for brevity
}
}
Run Code Online (Sandbox Code Playgroud)
它是这样使用的:
val f = new DAOFactory[DAOTodo]
val ShinyNewObject = f.doFoo() // 永远不会到达这里。
'DAOTodo' 实际上是一个实现 DAO 特性的类:
class DAOTodo extends DAO {
def doSomethingSmart(when: Whenever) = {...}
}
Run Code Online (Sandbox Code Playgroud)
Q:使用DAO作为obj的doSomethingSmart函数的接口需要在A点做什么?
提前致谢。
答案: 除了下面的答案中概述的代码修改之外,由于正在创建的类(在工厂内)的谱系具有未完成的主构造函数,因此未按预期运行。创建一个额外的零参数构造函数解决了这个问题。
尝试更改此行:
val dao = obj.asInstanceOf[DAO]
Run Code Online (Sandbox Code Playgroud)
对此:
val dao = obj.newInstance().asInstanceOf[DAO]
Run Code Online (Sandbox Code Playgroud)
您不能将Class[T]转换为DAOtrait的实例,所以我假设您想要做的是从类类型实例化一个新实例。
但是为了让它更好,你可以像这样定义你的工厂:
class DAOFactory[T <: DAO](implicit m: Manifest[T]) {
Run Code Online (Sandbox Code Playgroud)
然后将该行更改为如下所示:
val dao = obj.newInstance()
Run Code Online (Sandbox Code Playgroud)
删除那里的强制转换是可能的,因为您将 T 的类型限制为包含 DAO 特征。
将它们放在一起(使用几个小模块),此代码使用 Scala 2.10 为我成功运行:
import java.util.Date
object DAOTest{
def main(args: Array[String]) {
val fact = new DAOFactory[DAOTodo]
fact.doFoo
}
}
class DAOFactory[T <: DAO](implicit m: Manifest[T]) {
def obj = m.runtimeClass.asInstanceOf[Class[T]]
def doFoo(): Option[Any] = {
val dao = obj.newInstance()
println(obj.toString())
val bar = dao.doSomethingSmart(new Date)
return Some(obj)
}
}
class DAOTodo extends DAO {
def doSomethingSmart(date:Date) = {}
}
trait DAO{
def doSomethingSmart(date:Date)
}
Run Code Online (Sandbox Code Playgroud)