scala:以可继承的方式检索用于构造类实例的参数?

时间:2011-05-19 08:58:35

标签: scala reflection

在scala中,我有一种基类/特征被很多子类扩展的情况。我将通过获取类的名称和用于实例化类的参数来序列化子类的实例(以便稍后重构它)。使用反射很容易得到类实例的名称,但我不知道如何以不需要我在每个子类中编写代码的方式获取实例的参数。这也需要适用于名称调用的参数。它似乎很棘手,因为每个子类可能有一个完全不同的数量和类型的构造函数参数:

abstract class Base {
  // ideally implements some way of finding out the arguments used to construct this object
  def getArgs = {...}
}

class ChildA() // args would be a 0-tuple

class ChildB(arg1: Int) // getArgs would be a 1-tuple of arg1

class ChildC(arg1: Double, arg2: Boolean) // args would be a 2-tuple of (arg1, arg2)

// etc... 

我想避免的是让每个类实现一个像“getArgs”这样的方法,只返回一个元组,复制构造函数中的参数。任何方式这样做?

我意识到另一种方法是使用某种拦截器来创建对象,但我无法弄清楚如何在不必为每个子类编写样板代码的情况下这样做。

编辑:案例类方法很优雅,但在我的情况下是不合适的,因为我们必须能够允许具体的子类扩展其他具体的子类。

1 个答案:

答案 0 :(得分:9)

如果您的目标是避免在每个子类中编写代码来捕获参数,并且所有子类都处于平面层次结构中,直接继承自Base而不是彼此继承,则应考虑将它们声明为{ {1}}而是。然后,他们会自动延长Product,您可以使用case class来例如{}将所有args保存到productIterator(我正在使用Array[Any],因为这是您稍后反思性地调用这些类的构造函数时所需要的内容):

Array

如果您希望scala> def toArray(p: Product) = p.productIterator.toArray toArray: (p: Product)Array[Any] scala> case class ChildA() defined class ChildA scala> toArray(ChildA()) res0: Array[Any] = Array() scala> case class ChildB(arg1: Int) defined class ChildB scala> toArray(ChildB(42)) res1: Array[Any] = Array(42) 仅接受toArray的子类,请将其参数声明为Base