【发布时间】:2020-09-24 22:00:17
【问题描述】:
我有一个名为named 的基类,如下所示。它的主要构造函数有 4 个参数,flow1 和 flow2 的类型为 T0 和 T1,它们派生自抽象类 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()不是必须的,因为T0和T1是确定的,MyAnnoyingFlowParser的类型是确定的,所以其实我想要这个:
new EitherDataFrameOrRawFlow("")
更新:
EitherFlow中有很多构造函数,我想做如下
// original
new EitherFlow[DataFrameFlow, RawFlow](new MyAnnoyingFlowParser(), a, b, c, ...)
// what I want
new EitherDataFrameOrRawFlow(a, b, c, ...)
我尝试了以下策略,但都遇到了一些问题。
-
尝试“currying”
apply方法 有了这个策略,我想我可以写这个val f1 = EitherDataFrameOrRawFlow("") val f2 = EitherDataFrameOrRawFlow(new RawFlow(), "")所以我决定写下面的代码,它实际上返回了一个匿名对象,它重载了
apply方法。我从这篇文章中采用了这个策略(Scala, currying and overloading)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 -
尝试创建一个新类并实现它自己的辅助构造函数
但是,当我尝试实现辅助构造函数
def this(d: Flow)时,我感到很困惑。 根据alexander,我不能直接调用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。
【问题讨论】:
-
您开始使用的代码不能使用
not enough arguments for constructor Flow编译:scastie.scala-lang.org/MzEiQW61Ta6ui56LzSSpyA 如果我注释掉(var outputName: String)它不会使用ambiguous implicit values编译:scastie.scala-lang.org/qeA70jcER4qj43CUYCe30A。请提供MCVE。 -
嗨@DmytroMitin,我有my codes edited,我使用可以编译的Scala 2.11.8
标签: scala constructor