通过反射将类名称传递给Scala中的超类构造函数

时间:2019-01-07 10:34:44

标签: scala reflection constructor

如何将类的名称传递给其超类构造函数,甚至有可能吗?我正在考虑这样的事情:

class TestClass extends SuperTestRequiringName(TestClass.getClass.getName) {}

这比将名称作为硬编码字符串传递要好,因为在重命名重构期间会保持一致性。

甚至最好是实际的运行时类,因此,如果可能的话,我会得到一个子类的名称。但这并不能正常工作:

class TestClass extends SuperTestRequiringName(this.getClass.getName) {}

我一般不问如何在运行时访问超类内部的子类名称。重要的是,可以将类名用作超级构造函数参数,以便超级类可以将其传递给自己的超级类(从我无法更改的库中)。

3 个答案:

答案 0 :(得分:2)

class TestClass extends SuperTestRequiringName(classOf[TestClass].getName)

在Scala中,classOf[A]与Java中的A.class相同。

getClass是一种方法,您只能在类的实例上调用。

答案 1 :(得分:1)

我不确定我是否正确理解您的问题,但是您可以为此使用ClassTag。例如;

import scala.reflect._
class SuperTestRequiringName(name: String) {}
class TestClass extends SuperTestRequiringName(classTag[TestClass].runtimeClass.getName)

希望对您有帮助!

答案 2 :(得分:1)

我认为您的问题没有很好的解决方案。 JVM内存模型的工作方式是,在调用基本构造函数之前,甚至不能获得自己的类名,也不能使用this。如果您从库的类继承的原因是重用其​​功能,而不是需要在使用基类的相同上下文中实际使用您的类,则建议将继承替换为composition无论如何,针对此类问题的正确解决方案。代码如下:

case class Wrapper(s: String)

class LibraryClass(val w: Wrapper) {
  def someUsefulStuff(n: Int): String = ???

  def someNotUsefulStuff(n: Int): String = ???
}

class Base() {
  private val delegate:LibraryClass = new LibraryClass(Wrapper(this.getClass.getName))

  // expose useful methods from the delegate
  // depending on logic maybe decorate them as protected
  def someUsefulStuff(n: Int): String = delegate.someUsefulStuff(n)
}

class LeafA extends Base

class LeafB extends Base

请参见示例online

如果确实需要从LibraryClass继承以便在这些上下文中使用,则可能必须像@ygor解决方案中那样,使子类显式传递字符串。