如何“实例化”超类中的抽象类?

时间:2019-04-04 15:36:03

标签: scala inheritance abstract-class companion-object

我正在Spark中实现ml.Transformer的扩展;但是这个问题是Scala特有的。这是一个示例对象(类/对象对的一部分):

abstract class UDFTransformer(func: UserDefinedFunction,
                     inputFieldNames: Seq[String],
                     outputFieldName: String) extends Transformer with MLWritable with Serializable {
  ... definitions here ...
}

object UDFTransformer extends MLReadable[UDFTransformer] {

  // Since there are no parameters associted with the UDF, there is nothing to save!
  class Writer(instance: UDFTransformer) extends MLWriter {
    override protected def saveImpl(path: String): Unit = {}
  }
  abstract protected class Reader extends MLReader[UDFTransformer]

  override def read: MLReader[UDFTransformer] = new Reader

  override def load(path: String): UDFTransformer = super.load(path)

}

new Reader无法编译,因为该类是抽象的并且无法实例化。但;任何子类都必须对其进行定义;及其必要的成员。我也不能仅使read变得抽象,这给了我一个警告Only classes can have declared but undefined methods.

基本问题是我的UDFTransformer的每个子类都将包装一个特定的UDF。因此,阅读器需要能够生成特定的UDF对象。这不能在超类中声明。但是这个“工厂”属于同伴对象,而不是抽象类本身。

我该如何为抽象类构建一个伴随对象,而该抽象类可以使read的定义保持未定义?

1 个答案:

答案 0 :(得分:2)

通常的方法是为伴随对象创建一个抽象类或特征。像

abstract class UDFTransformerCompanion[T <: UDFTransformer] extends MLReadable[T] {

  abstract def read: MLReader[T]

  override def load(path: String): T = super.load(path)

}

class SomeTransformer extends UDFTransformer { ... }

object SomeTransformer extends UDFTransformerCompanion[SomeTransformer] { 
  override def read: MLReader[SomeTransformer] = ...
}

不确定为什么要使用load = super.load覆盖,而且似乎无法为UDFTransformer本身提供一个伴随对象,至少没有一个扩展此抽象类。

有关标准库示例,请参见GenericTraversableTemplate