简体   繁体   English

使用 classOf Scala 键入不匹配的泛型

[英]Type mismatch generics with classOf Scala

I have a method that should dynamically cast a field member into a certain type depending on a configuration flag format .我有一种方法可以根据配置标志format将字段成员动态转换为特定类型。

This flag format , accepts one of the following type values:此标志format接受以下类型值之一:

object Types {
    val Str = "string"
    val IntNum1 = "int"
    val IntNum2 = "integer"
    val DoubleNum = "double"
    val LongNum = "long"
}

One option would be to use reflection.一种选择是使用反射。 Another option would be to use pattern matching (the method I'm trying to do this with)另一种选择是使用模式匹配(我正在尝试使用的方法)

Here's the method for String types:下面是String类型的方法:

private def getValClassIfStr(format: String): Class[String] = {
    format.toLowerCase match {
        case Types.Str => classOf[String]
        case _ => null
    }
}

And Here's the method for Numerical types, extending from AnyVal , that fails to compile:这是从AnyVal扩展的数字类型的方法,它无法编译:

private def getValueClass[T <: AnyVal](format: String): Try[Class[T]] = {
    format.toLowerCase match {
        case Types.IntNum1 || Types.IntNum2 => Success(classOf[Int])
        case Types.DoubleNum => Success(classOf[Double])
        case Types.LongNum => Success(classOf[Long])
        case _ => Failure(new Exception)
    }
}

The second method doesn't compile because of a: Type mismatch: required Try[Class[T]] found Try[Class[Int]]由于以下原因,第二种方法无法编译: Type mismatch: required Try[Class[T]] found Try[Class[Int]]

Which I don't understand, given T <: AnyVal .我不明白,给定T <: AnyVal

Any idea?任何的想法? and if that's a bad approach, what would a "clean" alternative be?如果这是一个糟糕的方法,那么“干净”的替代方案是什么?

I think the reason why this doesn't work becomes clearer once you replace Class[T] in the return value with Class[AnyVal] :我认为一旦你用Class[AnyVal]替换返回值中的Class[T] ,为什么这不起作用的原因变得更加清晰:

type mismatch;
 found   : Class[Int](classOf[scala.Int])
 required: Class[AnyVal]
Note: Int <: AnyVal, but Java-defined class Class is invariant in type T.
You may wish to investigate a wildcard type such as `_ <: AnyVal`. (SLS 3.2.10)

In other words, any call to getValueClass[T] would always have to be populated with T = AnyVal by the compiler, since format is only evaluated at runtime.换句话说,任何对getValueClass[T]调用总是必须由编译T = AnyVal填充,因为format只在运行时进行评估。 This, however, is not possible since Class[T] is invariant, so you can't return a Class[Int] and a Class[Double] as a Class[AnyVal] , since for invariant containers there's no subtyping relationship.但是,这是不可能的,因为Class[T]是不变的,因此您不能将Class[Int]Class[Double]作为Class[AnyVal] ,因为对于不变容器,没有子类型关系。

To demonstrate:展示:

var x: Class[AnyVal] = _
x = classOf[Int]
// Boom

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

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