我有一个名为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, ...)
我尝试了以下策略,但在这两种策略中都遇到了一些问题。
尝试"咖喱;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
尝试创建一个新类并实现自己的辅助构造函数
然而,当我试图实现辅助构造函数
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