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

scala:检索用于以可继承方式构造类实例的参数?,scala,reflection,Scala,Reflection,在scala中,我遇到了一个基类/特征被很多子类扩展的情况。我将通过获取类的名称和用于实例化该类的参数来序列化子类的实例(为了以后重建它)。使用反射很容易获得类实例的名称,但我不确定如何以不需要在每个子类中编写代码的方式获得实例的参数。这也需要用于名为的参数。这看起来很棘手,因为每个子类可能都有完全不同数量和类型的构造函数参数: abstract class Base { // ideally implements some way of finding out the arguments

在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”这样的方法,并且只返回一个元组来复制构造函数中的参数。有办法吗

我意识到另一种方法是使用某种拦截器来创建对象,但如果不为每个子类编写样板代码,我就不知道如何做到这一点


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

如果您的目标是避免在每个子类中编写代码来捕获参数,并且所有子类都在一个平面层次结构中,直接从<代码> Base<代码>中继承,而不是相互继承,应该考虑将它们声明为<代码> case类< /代码> ES。然后它们会自动扩展,您可以使用和
productIterator
将所有参数保存到
Array[Any]
(我使用的是
Array
,因为这是以后反射调用这些类的构造函数时所需要的):


如果希望
toArray
只接受
Base
的子类,则将其参数声明为
带Base的产品

@jean-philippe不幸的是,有些子类扩展了其他子类。这是否破坏了这一计划?看来case类继承已经被弃用了。@Heinrich实际上,不幸的是,这破坏了这种技术。(这就是为什么我写了“如果[…]子类在平面层次结构中”。@Heinrich层次结构不需要是完全平面的,但非叶类不能是case类。如果非叶类可以是抽象的(也就是说,你永远不会直接实例化它们),这个解决方案仍然适用于你。但是请记住,
productIterator
返回的值不会包括抽象超类中的
val
s。是的,这正是我在邮件列表中建议的。还要注意经常重复的格言,“每个类都应该是抽象的或最终的。”
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)