我正在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
的定义保持未定义?
答案 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
。