【问题标题】:How do I get an object's type and pass it along to asInstanceOf in Scala?如何获取对象的类型并将其传递给 Scala 中的 asInstanceOf?
【发布时间】:2013-11-23 20:57:49
【问题描述】:

我有一个 Scala 类,它从 JOSN 模板文件中读取格式信息,并从不同的文件中读取数据。目标是格式化为模板文件指定的 JSON 对象。我正在使布局正常工作,但现在我想将输出的类型设置为模板中的类型(即,如果我在模板中有一个字段值作为字符串,那么它应该是输出中的字符串,甚至如果它是原始数据中的整数)。

基本上,我正在寻找一种快速简便的方法来执行以下操作:

output = dataValue.asInstanceOf[templateValue.getClass]

该行给了我一个错误,即 getClass 类型不是 Any 的成员。但是我找不到任何其他在运行时为我提供变量类型的成员或方法。这可能吗?如果可以,怎么做?

澄清

我应该在我的代码中补充一点,我知道我正在处理一个键/值对。我想要的是值的类型。

具体来说,给定下面的 JSON 模板,我希望将名称转换为字符串,将年龄转换为整数,并将薪水转换为输出的小数,无论它在原始数据文件中如何显示 (它可以是所有字符串,年龄和薪水都可以是整数等)。我希望的是一个简单的转换,不需要我进行模式匹配来专门处理每种数据类型。

示例模板:

people: [{  
    name: "value",  
    age: 0,  
    salary: 0.00  
}]

【问题讨论】:

    标签: scala scala-2.10


    【解决方案1】:

    类型参数必须在编译时已知(类型符号),而templateValue.getClass 只是一个普通值(Class 类型),因此不能用作类型参数。 该怎么做 - 这取决于你的目标,这对我来说还不清楚......但它可能看起来像

    output = someMethod(dataValue, templateValue.getClass),

    在该方法中,您可以根据Class 类型的第二个参数进行不同的计算。

    【讨论】:

      【解决方案2】:
      1. 如何获取对象的类型并将其传递给 Scala 中的 asInstanceOf?

        方法scala.reflect.api.JavaUniverse.typeOf[T] 要求它的类型参数由调用者硬编码或类型推断。要进行类型推断,请创建一个如下所示的实用方法(适用于所有类型,甚至泛型 - 它通过在编译期间使用类型标记元数据增加 T 来抵消 java 运行时类型 arg 擦除):

        // http://www.scala-lang.org/api/current/index.html#scala.reflect.runtime.package
        import scala.reflect.runtime.universe._   
        def getType[T: TypeTag](a: T): Type = typeOf[T]
        

        这里有 3 个要求:

        • 类型 arg 实现 TypeTag(但之前通过 Manifest 实现的仍然可用...)
        • 输入一个或多个输入参数 T
        • 返回类型为 Type(如果您希望结果在方法外部使用)

        您可以在不指定 T 的情况下调用(它是类型推断的):

        import scala.reflect.runtime.universe._
        def getType[T: TypeTag](a: T): Type = typeOf[T]
        val ls = List[Int](1,2,3)
        println(getType(ls))  // prints List[Int]
        

        但是,asInstanceOf 只会将该类型转换为层次结构中的(二进制一致)类型,而不转换数据或格式。即数据必须已经是正确的二进制格式 - 这样不会解决您的问题。

      2. 数据转换

        在整数和字符串之间转换的几种方法:

        // defined in scala.Any:
        123.toString                  // gives "123"
        // implicitly defined for java.lang.String via scala.collection.immutable.StringOps:
        123.toHexString               // gives "7b"
        123.toOctalString             // gives "173"
        "%d".format(123)              // also gives "123"
        "%5d".format(123)             // gives "  123"
        "%05d".format(123)            // gives "00123"
        "%01.2f".format(123.456789)   // gives "123.46"
        "%01.2f".format(123.456789)   // gives "0.46"
        
        // implicitly defined for java.lang.String via scala.collection.immutable.StringOps:
        "  123".toInt                 // gives 123
        "00123".toInt                 // gives 123
        "00123.4600".toDouble         // gives 123.46
        ".46".toDouble                // gives 0.46
        
      3. 直接从文件解析到目标类型(无强制转换或转换):

        不幸的是,scala 没有将流中的下一个标记读取为整数/浮点数/短/布尔值/等的方法。但是您可以通过获取 java FileInputStream,将其包装在 DataInputStream 中,然后调用 readIntreadFloatreadShortreadBoolean 等来做到这一点。

      【讨论】:

        【解决方案3】:

        在类型级上下文中,值级术语仍然有一些访问器。第一个和你要求的那个是值本身的类型(type):

        output = dataValue.asInstanceOf[templateValue.type]
        

        如果值的类型有内部成员,这些成员也可用:

        class A {
          class B {}
        }
        
        val a: A = new A
        val b: a.B = new a.B
        

        通知b: a.B

        我还必须提到如何在没有价值级别术语的情况下访问此类成员:

        val b: A#B = new a.B
        

        【讨论】:

          猜你喜欢
          • 2016-09-02
          • 1970-01-01
          • 2012-07-20
          • 2013-06-13
          • 2011-04-20
          • 1970-01-01
          • 2015-10-08
          • 2018-09-09
          • 2020-01-28
          相关资源
          最近更新 更多