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

如何从Scala子类的构造函数中消除参数,scala,constructor,Scala,Constructor,我有一个名为的基类,名为,如下所示。它的主构造函数采用4个参数,flow1和flow2的类型为T0和T1,它们是从抽象类Flow派生的。谓词参数是流解析器的对象,对于不同的流,可以有不同的流解析器 现在我想在子类中删除 import scala.reflect.ClassTag import scala.reflect._ abstract class Flow() extends Serializable { } trait FlowParser extends Serializabl

我有一个名为
的基类,名为
,如下所示。它的主构造函数采用4个参数,
flow1
flow2
的类型为
T0
T1
,它们是从抽象类
Flow
派生的。
谓词
参数是
流解析器
的对象,对于不同的
,可以有不同的
流解析器

现在我想在子类中删除

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]
    }
  }
}
但是,
new MyHatteringFlowParser()
不是必需的,因为给定的
T0
T1
是确定的,
MyHatteringFlowParser
的类型是确定的,所以实际上我想要:

new EitherDataFrameOrRawFlow("")
更新:

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

// original
new EitherFlow[DataFrameFlow, RawFlow](new MyAnnoyingFlowParser(), a, b, c, ...)
// what I want
new EitherDataFrameOrRawFlow(a, b, c, ...)
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]
    }
  }
}
我尝试了以下策略,但都遇到了一些问题

  • 尝试“套用”
    apply
    方法 有了这个策略,我想我可以写这个

    val f1 = EitherDataFrameOrRawFlow("")
    val f2 = EitherDataFrameOrRawFlow(new RawFlow(), "")
    
    所以我决定写下面的代码,它实际上返回一个匿名对象,它重载了
    apply
    方法。我在这篇文章中采用了这个策略()

  • 尝试创建一个新类并实现它自己的辅助构造函数

    然而,当我尝试实现辅助构造函数时,我感到困惑
    def this(d:Flow)
    。 根据,我不能直接调用super的辅助构造函数。所以我必须像下面这样写

    // original
    new EitherFlow[DataFrameFlow, RawFlow](new MyAnnoyingFlowParser(), a, b, c, ...)
    // what I want
    new EitherDataFrameOrRawFlow(a, b, c, ...)
    
    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)
    }
    
    而且根本不做子类

    我不清楚您是传递了一个新的
    MyHappingFlowParser
    还是传递了一个新的
    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
    
    看看您的代码,似乎只有一个正确的
    DataFlowParser
    实现。因此,将其隐式化是合乎逻辑的途径。但我们无法深入了解您的设计和约束

    考虑到限制因素

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

    object EitherDataFrameOrRawFlow {
      def apply(fl: Flow) = new EitherFlow[DataFrameFlow, RawFlow](new MyAnnoyingFlowParser(), fl)
    }
    
    而且根本不做子类

    我不清楚您是传递了一个新的
    MyHappingFlowParser
    还是传递了一个新的
    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
    

    您开始使用的代码编译时未使用
    构造函数流的参数不足
    :如果我注释掉
    (var outputName:String)
    它不会使用
    不明确的隐式值进行编译
    :。请提供.Hi@DmytroMitin,我有,并且我使用Scala 2.11.8,它可以编译您开始使用的代码没有使用
    足够的构造函数流参数进行编译
    :如果我注释掉
    (var outputName:String)
    它不会使用
    不明确的隐式值进行编译
    :。请提供.Hi@DmytroMitin,我有,我使用Scala 2.11.8,它可以编译Hi Martjin,这不是真的“看起来DataFlowParser只有一个正确的实现”。对于
    EitherFlow[DataFrameFlow,RawFlow]
    我可以拥有
    EitherDataFrameOrRawFlow
    ,但是,也会有其他
    EitherFlow
    ,比如
    EitherFlow[DataFrameFlow,RDDFlow]
    ,因此会有多个子类继承
    FlowParser
    ,我已经考虑过你的解决方案,但这是可行的,对于
    EitherFlow
    的每一个子类,我都必须实现
    apply
    的多个重载,这只需转发它的一些参数(除了第一个
    FlowParser
    参数),我认为这会导致大量冗余代码。@calvin专用类型的多个apply方法不是您最初问题的一部分。你能简明扼要地指出你的设计约束到底是什么以及必须实现什么吗?你说“这样它们就没有类型参数”,但是,我认为如果
    T0
    T1
    在运行时不可见,编译器是否应该警告“由于它被擦除而被取消选中”或其他什么?然而,我没有看到这样的警告。我不知道如果“没有类型参数”,是否会有任何副作用,因为模式匹配在这里仍然有效?@calvin如果你需要检查某个值是否有某个特定的类型,其中类型,你需要一个TypeTag,yesHi Martjin,那么“看起来DataFlowParser只有一个正确的实现”就不是真的。对于
    EitherFlow[DataFrameFlow,RawFlow]
    我可以拥有
    EitherDataFrameOrRawFlow
    ,但是,会有其他
    EitherFlow
    s,比如
    EitherFlow[DataFrameFlow,RDDFlow]
    ,因此会有多个子类继承
    FlowParser
    A