我有很多类,例如DataFrameFlow
,TextFlow
,RDDFlow
。它们都源自基类Flow
。
现在,我想编写一个函数judgeFlow
,该函数可以从path: String
中读取并返回代表确切Flow
类型的内容,从中可以创建相应的实例。整个代码如下所示
def judgeFlow(path:String) = /*1*/ {
Flow.getStoreType(path) match {
case StoreType.tdw =>
DataFrameFlow
case StoreType.hdfs =>
TextFlow
}
}
def createFlow(typeInfo:/*2*/) = /*3*/{
new typeInfo()
}
但是,我不知道如何在位置1、2和3处书写。
编辑
在这里仅仅知道如何构造它们是不够的,因为我还想要以下内容:
typeInfo
的asInstanceOf
编辑2
Flow
的定义
abstract class Flow(var outputName: String) extends Serializable{
def this() = this("")
...
}
DataFrameFlow
的定义
class DataFrameFlow(d: DataFrame, path: String) extends Flow {
var data: DataFrame = d
def this(data: DataFrame) = this(data, "")
def this(path: String) = this(null, path)
def this() = this(null, "")
...
}
答案 0 :(得分:2)
模式匹配无法在不同情况下返回不同的类型。模式匹配返回的类型是在情况下返回的类型的最小上限。
当某人想要返回不同的类型时,很可能他/她想要一个类型类。
sealed abstract class Flow
class DataFrameFlow extends Flow
class TextFlow extends Flow
class RDDFlow extends Flow
trait JudgeFlow[In] {
type Out <: Flow
def judgeFlow(in: In): Out
}
object JudgeFlow {
implicit val `case1`: JudgeFlow[???] { type Out = DataFrameFlow } = ???
implicit val `case2`: JudgeFlow[???] { type Out = TextFlow } = ???
implicit val `case3`: JudgeFlow[???] { type Out = RDDFlow } = ???
}
def judgeFlow[In](in: In)(implicit jf: JudgeFlow[In]): jf.Out = jf.judgeFlow(in)
但是麻烦的是类型是在编译时解析的。您似乎想基于字符串的值来选择一种情况,即在运行时。因此,在编译时,您只能返回Flow
以外的其他特定类型。
flatMap with Shapeless yield FlatMapper not found
很难完全猜出您的用例。
但是使用Scala reflection可以尝试
import scala.reflect.runtime.universe._
import scala.reflect.runtime.currentMirror
def judgeFlow(path:String): Type = {
Flow.getStoreType(path) match {
case StoreType.tdw =>
typeOf[DataFrameFlow]
case StoreType.hdfs =>
typeOf[TextFlow]
}
}
def createFlow(typeInfo: Type): Flow = {
val constructorSymbol = typeInfo.decl(termNames.CONSTRUCTOR).asMethod
val classSymbol = typeInfo.typeSymbol.asClass
val classMirror = currentMirror.reflectClass(classSymbol)
val constructorMirror = classMirror.reflectConstructor(constructorSymbol)
constructorMirror().asInstanceOf[Flow]
}