Scala中的条件类型变量

时间:2018-09-16 16:08:28

标签: scala

我试图在条件if-else之后在Scala中定义变量“类型”。

目的是获得像type In = xxx这样的变量。这样就可以实例化参数化的类或调用参数化的函数。给出定义:

  class MyParamClass[T: TypeTag](context: String){...}
  def startStrean[T: TypeTag](context: String) = {...}

我想创建一个MyParamClass[T](context = "my contentx")的实例,其中T取决于配置字符串。用户可以使用API​​提供配置字符串。

  val conf = Option("Map[String, Any]")

  //get the data types from the context
  type In = conf match {
    case Some("Map[String, Int]") =>      Map[String, Int]
    case Some("Map[String, Double]") =>   Map[String, Double]
    case Some("List[Double]") =>          List[Double]
    case Some("List[Int]") =>             List[Int]
    case None =>                          Map[String, Any]
  }

注意:先前的代码段无法编译。

然后,创建类或执行函数:

val context = "my context"
val pc = new MyParamClass[In](context)
startStream[In](context)

请注意,类型T不能从参数类型中推断出来。

看着Scala reflection documentation,我看到了一些方法。但是,我在玩tq

我遇到的主要问题是如何在运行时定义类型变量type In

2 个答案:

答案 0 :(得分:0)

我删除了先前的答案,因为它实际上并未回答上述问题。多亏了问题中的评论,我得出了适用于我的情况的以下解决方案。

问题在于类型不能在运行时生成,只能在编译类型时生成。因此,我必须为每个输入conf字符串编写调用。

import scala.reflect.runtime.universe._
import scala.tools.reflect.ToolBox

val mirror = runtimeMirror(getClass.getClassLoader)
val tb = mirror.mkToolBox()

def typecheckType(tree: Tree): Type = tb.typecheck(tree, tb.TYPEmode).tpe

typecheckType(tq"$context") match {
        case tpe if tpe =:= typeOf[Map[String, _]] =>
          startStrean[Map[String, Any], Map[String, Any]](context = context)
        case tpe if tpe =:= typeOf[Map[String, Double]] =>
          startStrean[Map[String, Double], Map[String, Double]](context = context)
        case tpe if tpe =:= typeOf[Map[String, Int]] =>
          startStrean[Map[String, Int], Map[String, Int]](context = context)
        case tpe if tpe =:= typeOf[List[Double]] =>
          startStrean[List[Double], List[Double]](context = context)
        case tpe if tpe =:= typeOf[String] =>
          startStrean[String, String](context = context)
        case tpe if tpe =:= typeOf[Int] =>
          startStrean[Int, Int](context = context)
        case tpe if tpe =:= typeOf[Double] =>
          startStrean[Double, Double](context = context)
        case _ =>
          startStrean[Map[String, Any], Map[String, Any]](context = context)
        }

上一个代码的作用是:

  • scala-reflection导入Universe。文档here
  • 使用quasiquotes进行类型检查。文档herehere
  • 使用在编译时可用的TypeTag创建函数

答案 1 :(得分:0)

您是否正在寻找类似的东西?

class MyParamClass[T](context: String) {
    def apply() {
        context match {
            case "Map[String, Int]"    => new MyParamClass[Map[String, Int]](context)
            case "Map[String, Double]" => new MyParamClass[Map[String, Double]](context)
            case _ => new MyParamClass[Map[String, Any]](context)
    }
}

}

然后您可以输入键入的类:val clazz: MyParamClass[_] = new MyParamClass("Map[String, Long]")