如何在Scala的子类中从构造函数中删除参数



我有一个名为named的基类,如下所示。它的主构造函数采用4个参数,flow1flow2的类型为T0T1,它们是从抽象类Flow派生而来的。predicate参数是FlowParser的对象,对于不同的EitherFlow,可以有不同的FlowParser

现在我想在子类中删除。

import scala.reflect.ClassTag
import scala.reflect._

abstract class Flow() extends Serializable {
}
trait FlowParser extends Serializable {
def judgeIndex(path: String): Int
def createFlow(path: String): Flow
}
class EitherFlow[T0 >: Null <: Flow: ClassTag, T1 >: Null <: Flow: ClassTag](
predicate: FlowParser,
var flow1: T0,
var flow2: T1,
var path: String) extends Flow{
def this(predi: FlowParser, path: String) = this(predi, null, null, path)
def this(predi: FlowParser) = this(predi, "")
protected def this(predi: FlowParser, index: Int, d: Flow) {
this(predi, null, null, "")
if (index == 0) {
this.flow1 = d.asInstanceOf[T0]
} else {
this.flow2 = d.asInstanceOf[T1]
}
}
def this(predi: FlowParser, d: Flow) {
this(predi, null, null, "")
d match {
case _: T0 => this.flow1 = d.asInstanceOf[T0]
case _: T1 => this.flow2 = d.asInstanceOf[T1]
}
}
}

现在我有许多来自EitherFlow的子类,比如EitherFlow[DataFrameFlow, RawFlow]。所以我可以写这样的代码

new EitherFlow[DataFrameFlow, RawFlow](new MyAnnoyingFlowParser(), "")

然而,new MyAnnoyingFlowParser()是不必要的,因为给定T0T1是确定的,MyAnnoyingFlowParser的类型是确定的。所以实际上我想要这个:

new EitherDataFrameOrRawFlow("")

更新:

EitherFlow中有许多构造函数,我想做以下

// original
new EitherFlow[DataFrameFlow, RawFlow](new MyAnnoyingFlowParser(), a, b, c, ...)
// what I want
new EitherDataFrameOrRawFlow(a, b, c, ...)

我尝试了以下策略,但在这两种策略中都遇到了一些问题。

  1. 尝试"咖喱;CCD_ 18方法有了这个策略,我想我可以写这个

    val f1 = EitherDataFrameOrRawFlow("")
    val f2 = EitherDataFrameOrRawFlow(new RawFlow(), "")
    

    所以我决定写下面的代码,它实际上返回了一个匿名对象,它重载了apply方法。我采用了这篇文章中的策略(Scala,currying和重载(

    object EitherFlow {
    def apply[T0 >: Null <: Flow: ClassTag, T1 >: Null <: Flow: ClassTag](predicate: FlowParser) =
    new {
    def apply[R >: Null <: Flow: ClassTag](flow: R, path: String): EitherFlow[T0, T1] = {
    val ret = new EitherFlow[T0, T1](predicate, flow)
    ret.path = path
    ret
    }
    def apply(path: String): EitherFlow[T0, T1] = {
    new EitherFlow[T0, T1](predicate, null.asInstanceOf[T0], null.asInstanceOf[T1], path)
    }
    }
    }
    

    但是,对于这种策略,我必须明确使用.apply。或者,它将导致错误

    com.xxx.flow.EitherDataFrameOrRawFlow.type does not take parameters
    
  2. 尝试创建一个新类并实现自己的辅助构造函数

    然而,当我试图实现辅助构造函数def this(d: Flow)时,我感到困惑。根据亚历山大的说法,我不能直接调用super的aux构造函数。所以我必须像下面的一样写作

    class EitherDataFrameOrRawFlow(var f1: DataFrameFlow, var f2: RawFlow, path: String) extends EitherFlow[DataFrameFlow, RawFlow](new DataFrameRawFlowParser(), f1, f2, path) {
    def this(d: Flow) {
    this(null, null, "")
    d match {
    case _: DataFrameFlow => this.flow1 = d.asInstanceOf[DataFrameFlow]
    case _: RawFlow => this.flow2 = d.asInstanceOf[RawFlow]
    }
    }
    }
    

    然而,我认为代码并不整洁。首先,我必须编写重复的代码,如d match {...}。其次,我必须定义重复的参数,如f1/f2

查看您的代码,似乎只有一个正确的DataFlowParser实现。因此,使其隐含是合乎逻辑的途径。但我们无法深入了解您的设计和限制。

给定限制条件

  • flow1和flow2都是var的,两者都不能或都不能为null,都有一个可用的类标签,可以在擦除时充分识别值(因此它们没有类型参数(
  • 您希望能够调用EitherDataFrameOrRawFlow(fl: Flow)并返回类型为EitherFlow[DataFrameFlow, RawFlow]的值

我只想做

object EitherDataFrameOrRawFlow {
def apply(fl: Flow) = new EitherFlow[DataFrameFlow, RawFlow](new MyAnnoyingFlowParser(), fl)
}

并且根本不生成子类。

我不清楚你是通过了新的MyAnnoyingFlowParser还是通过了新DataFrameRawFlowParser,但你可以自己换掉。

编辑:你也可以为对象创建一个基类:

abstract class PartiallyAppliedEitherConstructor[Flow1, Flow2](parser: => FlowParser) {
def apply(fl: Flow) = new EitherFlow[Flow1, Flow2](parser)
def apply(index: Int, flow: Flow) = new EitherFlow[Flow1, Flow2)(parser, index, flow)
//etc
}
object EitherDataFrameOrRawFlow extends PartiallyAppliedEitherConstructor[DataframeFlow, RawFlow](new MyAnnoyingFlowParser())
object EitherRddOrDataFrameFlow extends PartiallyAppliedEitherConstructor[RddFlow, DataFromeFlow](new SomeOtherFlowParser())
//etc

相关内容

最新更新