【问题标题】:Scala - Implementing a polymorphic abstract trait without polymorphismScala - 在没有多态的情况下实现多态抽象特征
【发布时间】:2016-07-02 12:31:51
【问题描述】:

我正在用 Scala 设计一个简单的数据处理管道。它涉及PipelineStage,其中transform 一些StageOutput 变成另一个StageOutputPipeline 是一系列 PipelineStage 的包装器,它需要一般地访问它们的所有 transform 方法。

但是我遇到了麻烦,因为我提出的两种解决方案基本上都不起作用......第一个依赖于以非多态方式实现的抽象多态方法(不编译)和第二个依赖于能够使用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 方法的签名虽然他们“尊重”抽象签名的多态性,但它们本身实际上并不是多态的,所以不要就编译器而言匹配。

场景 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]
    }

这解决了PipelineStages 的问题,他们编译没有问题,并且他们的转换方法可以自己正常工作。但是,它们现在在技术上没有实现相同的特征,所以 Pipeline 无法编译,因为 Seq[PipelineStage] 现在没有意义了......

是否有既定的模式来实现没有多态性的多态抽象方法,或者引用实现相同抽象多态特征的一系列类?我的感觉是不,我可能以错误的方式处理这个问题,但也许我在某个地方遗漏了一个句法技巧。谢谢。

【问题讨论】:

  • 尝试填写Pipeline 方法的主体,假设您可以通过某种方式编译它,并且可以访问def stages: Seq[PipelineStage]。显示您计划如何使用该功能。

标签: scala functional-programming polymorphism


【解决方案1】:

第一个根本没有做你想做的事:def transform[StageOutput1, StageOutput2](in: StageOutput1): StageOutput2 中的StageOutput12 只是参数名称,它的含义与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 基本上是一个带有约束的Function1;如果您不打算添加其他方法,或者有意限制可以编写的阶段种类,您可能只想使用函数并利用标准库!)

【讨论】:

  • 你说得对,编辑删除了第一个场景的PipelineStage1transform方法中的多态性。是一个错字,而不是我试图编译的。另外,我在PipelineStage 上确实有其他几种方法和属性,所以我确实需要使用特征。但是,我并没有真正考虑过PipelineStagePipeline 之间没有根本不同的事实。我可以将我想要的所有方法放在PipelinePipelineStage 并使用您的撰写功能。谢谢!
  • 实际上,我建议称它为Pipeline 而不是PipelineStage
猜你喜欢
  • 2012-12-10
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
  • 2021-10-16
  • 1970-01-01
  • 2011-09-09
  • 1970-01-01
相关资源
最近更新 更多