繁体   English   中英

Scala中的条件类型变量

[英]Conditional type variable in 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反射文档,我发现了一些方法。 但是,我在玩tq

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

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

问题是类型不能在运行时生成,只能在编译类型时生成。 因此,我必须为每个输入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导入宇宙。 这里的文件
  • 使用quasiquotes类型检查。 此处此处的文档
  • 使用在编译时可用的TypeTag创建函数

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

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]")

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM