0

我有一个用于 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 
   }
}

它是这样使用的:
val f = new DAOFactory[DAOTodo]
val shinyNewObject = f.doFoo() // 永远不会到达这里。

'DAOTodo' 实际上是一个实现 DAO 特征的类:

class DAOTodo extends DAO {
   def doSomethingSmart(when: Whenever) = {...}
}

Q:在“A”点需要做什么才能使用DAO作为“obj”的“doSomethingSmart”函数的接口?

提前致谢。

答案: 除了下面答案中概述的代码修改之外,由于正在创建的类的沿袭(在工厂内)有一个未实现的主构造函数,因此它没有按预期运行。创建一个额外的零参数构造函数解决了这个问题。

4

2 回答 2

5

尝试更改此行:

val dao = obj.asInstanceOf[DAO] 

对此:

val dao = obj.newInstance().asInstanceOf[DAO] 

您不能将Class[T]转换为DAO特征的实例,所以我假设您想要做的是从类类型实例化一个新实例。

但为了让它更好,你可以像这样定义你的工厂:

class DAOFactory[T <: DAO](implicit m: Manifest[T]) {

然后将该行更改为:

val dao = obj.newInstance()

删除演员表是可能的,因为您将 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)
}
于 2013-05-03T23:53:43.440 回答
0

在我看来,您使用 Manifest 是出于错误的原因。您应该使用反射 Api 中的运行时反射。Manifest 用于绕过参数化类型的类型擦除。你需要什么在这里解释:http: //docs.scala-lang.org/overviews/reflection/overview.html

于 2013-05-03T23:52:51.927 回答