Scala - 实现没有多态性的多态抽象特征

时间:2016-07-02 12:31:52

标签: scala functional-programming polymorphism

我在Scala中设计一个简单的数据处理管道。它涉及PipelineStagetransform一些StageOutput进入另一个StageOutputPipeline是一系列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]现在没有意义......

是否有既定的模式来实现没有多态性的多态抽象方法,或者引用实现相同抽象多态特征的类序列?我的感觉是否定的,而且我可能以错误的方式接近了这一点,但也许还有一个语法上的诡计,我在某个地方错过了。感谢。

1 个答案:

答案 0 :(得分:4)

第一个根本不能做你想做的事:StageOutput12中的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;如果您不打算添加其他方法,或故意限制可写入的各种阶段,您可能只想使用函数并利用标准库!)