在scala中,有什么方法可以返回类型吗?

时间:2020-09-22 03:09:56

标签: scala reflection types pattern-matching scala-reflect

我有很多类,例如DataFrameFlowTextFlowRDDFlow。它们都源自基类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
  1. 模式匹配
  2. 一些方法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, "")
...
}

1 个答案:

答案 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]
}