我在Scala中设计一个简单的数据处理管道。它涉及PipelineStage
,transform
一些StageOutput
进入另一个StageOutput
。 Pipeline
是一系列PipelineStage
的包装器,需要一般访问所有transform
方法。
但是我遇到了麻烦,因为我提出的两种解决方案基本上都没有工作......第一种方法依赖于以非多态方式实现的抽象多态方法(并不是#39; t compile)而第二个依赖于能够使用Seq[AbstractTrait]
AbstractTrait
是多态的,这对编译器来说也毫无意义。见如下......
场景1.使transform
方法具有多态性。
abstract trait PipelineStage {
def transform[A <: StageOutput, B <: StageOutput](in: A): B
}
class PipelineStage2 extends PipelineStage {
def transform(in: StageOutput1): StageOutput2
}
class Pipeline {
def stages: Seq[PipelineStage]
}
这里Pipeline
编译没有问题,但是这些阶段因为transform
方法的签名而不会编译,而他们尊重&#39;抽象签名的多态性,实际上并不是多态的,所以就编译器而言,它们并不匹配。
场景2.使PipelineStage
特征本身具有多态性。
abstract trait PipelineStage[A <: StageOutput, B <: StageOutput] {
def transform(in: A): B
}
class PipelineStage2 extends PipelineStage[StageOutput1, StageOutput2] {
def transform(in: StageOutput1): StageOutput2
}
class Pipeline {
def stages: Seq[PipelineStage]
}
这解决了PipelineStage
的问题,它们编译没有问题,并且它们的转换方法可以自行运行。但是,他们现在在技术上并没有实现相同的特性,所以Pipeline
无法编译,因为Seq[PipelineStage]
现在没有意义......
是否有既定的模式来实现没有多态性的多态抽象方法,或者引用实现相同抽象多态特征的类序列?我的感觉是否定的,而且我可能以错误的方式接近了这一点,但也许还有一个语法上的诡计,我在某个地方错过了。感谢。
答案 0 :(得分:4)
第一个根本不能做你想做的事:StageOutput1
和2
中的def transform[StageOutput1, StageOutput2](in: StageOutput1): StageOutput2
只是参数名称,它与{{1}完全相同}。
我的建议是使用第二个,但您可以添加def transform[A, B](in: A): B
而不是
class Pipeline
并构建您想要的管道,前提是类型实际匹配。
(另外,您的def compose[C <: StageOutput](other: PipelineStage[B, C]): PipelineStage[A, C] = new PipelineStage[A, C] {
def transform(in: A) = other.transform(PipelineStage.this.transform(in))
}
基本上是带有约束的PipelineStage
;如果您不打算添加其他方法,或故意限制可写入的各种阶段,您可能只想使用函数并利用标准库!)