如何从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都是
,两者都可以为null,都有一个可用的类标记,可以在擦除时充分标识值(因此它们没有类型参数)var
- 您希望能够调用
并返回类型为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都是
,两者都可以为null,都有一个可用的类标记,可以在擦除时充分标识值(因此它们没有类型参数)var
- 您希望能够调用
并返回类型为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