使用scala反射来启动具有内部对象的类

时间:2012-11-06 17:43:54

标签: scala reflection

我有一个这样的课程:

class NormalClass[T <: NormalClass[T]] {
  object One
  object Two
}

我希望能够在类型特征中创建上述类的新实例。 MetaClass中的以下def make创建T的实例,但它缺少与NormalClass关联的内部对象。

trait MetaClass[T <: NormalClass[T]] {
  def make:T = this.getClass.getSuperclass.newInstance.asInstanceOf[T]
} 

我有两个问题,缺少对象的原因是什么,以及使用反射从类型中启动具有内部对象的新类的最佳方法是什么

编辑:更多细节

我面临的问题是,如果我然后使用make创建一个实例,例如var f = make我尝试访问和对象方法,例如f.One.getSomething我收到错误value One is not a member of type parameter T

2 个答案:

答案 0 :(得分:3)

所以我认为你的问题尤其是反思:

this.getClass.getSuperclass.newInstance.asInstanceOf[T]

此处,this是您MetaClass的实例,并且没有特别的理由相信this的超类是您要实例化的类。例如:

class Foo extends NormalClass[Foo]
object Foo extends MetaClass[Foo]

在这种情况下,对象Foo的超类根本不是NormalClass,而是java.lang.Object。因此,它不会包含OneTwo等成员,如果您尝试将其转换为ClassCastException,则会获得T

如果希望make方法实例化T类型的对象,则需要获取T的运行时类,然后使用它来创建新实例。您可以通过隐式获取ClassTag

来实现此目的
class NormalClass[T <: NormalClass[T]] {
  object One
  object Two
}
trait MetaClass[T <: NormalClass[T]] {
  def make(implicit classTag: scala.reflect.ClassTag[T]): T =
    classTag.runtimeClass.newInstance.asInstanceOf[T]
}

// declare a class and an object for creating instances of that class
class Foo extends NormalClass[Foo]
object Foo extends MetaClass[Foo]

// create a new instance of Foo and access its fields
val foo = Foo.make
foo.One
foo.Two

答案 1 :(得分:1)

我不确定问题是什么。这对我有用:

scala> :paste
// Entering paste mode (ctrl-D to finish)

class NormalClass[T <: NormalClass[T]] {
  object One
  object Two
}

trait MetaClass[T <: NormalClass[T]] {
  def make:T = this.getClass.getSuperclass.newInstance.asInstanceOf[T]
} 

class X extends NormalClass[X]

// Exiting paste mode, now interpreting.

defined class NormalClass
defined trait MetaClass
defined class X

scala> new X with MetaClass[X]
res0: X with MetaClass[X] = $anon$1@404fe94c

scala> res0.One
res1: res0.One.type = NormalClass$One$@53d9f80

scala> res0.Two
res2: res0.Two.type = NormalClass$Two$@4d0948bd

如果这不能回答您的问题,请澄清您遇到的问题。