在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...
Run Code Online (Sandbox Code Playgroud)
我想避免的是让每个类实现一个像"getArgs"这样的方法,只返回一个元组,复制构造函数中的参数.任何方式这样做?
我意识到另一种方法是使用某种拦截器来创建对象,但我无法弄清楚如何在不必为每个子类编写样板代码的情况下这样做.
编辑:案例类方法很优雅,但在我的情况下是不合适的,因为我们必须能够允许具体的子类扩展其他具体的子类.
如果您的目标是避免在每个子类中编写代码来捕获参数,并且所有子类都处于平面层次结构中,直接继承Base而不是相互继承,则应考虑将它们声明为case classes.然后它们会自动扩展Product,你可以使用和productIterator保存所有args 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)
Run Code Online (Sandbox Code Playgroud)
如果只想toArray接受子类Base,则将其参数声明为Product with Base.