【问题标题】:Scala: can I get access to the type of a typed method?Scala:我可以访问类型化方法的类型吗?
【发布时间】:2015-07-03 19:51:17
【问题描述】:

我正在编写一个 DSL,我有一种情况,我希望将一个值隐式转换为任何类型。我创建了一个包装类,其中包含一个值和一个最有效的隐式方法:

case class ObjectOperationResult( val value: AnyRef )

object ObjectOperationResult {
    implicit def result2T[ T ]( result: ObjectOperationResult ): T = {
        result.value.asInstanceOf[ T ]
    }
}

如果 result.value 不是有效类型,代码将抛出异常;由用户来确保他们在做正确的事情。但是,我想通过根据目标类型执行不同的逻辑来使其更智能。例如,如果目标类型是 String 调用 toString 而不是 asInstanceOf[];像这样:

case class ObjectOperationResult( val value: AnyRef )

object ObjectOperationResult {
    implicit def result2T[ T ]( result: ObjectOperationResult ): T = {
        match T {
            case String s: result.value.toString
            case _ : result.value.asInstanceOf[ T ]
        }
    }
}

这不能编译;有什么方法可以确定 T 的类型,以便我采取相应的行动?

【问题讨论】:

    标签: scala methods implicit typed


    【解决方案1】:

    你可以定义多个函数,比如

    object ObjectOperationResult {
        implicit def toString( result: ObjectOperationResult ): String =  result.value.toString.trim
        implicit def toInt( result: ObjectOperationResult ): Int = result.value.asInstanceOf[Int]
    }
    

    由于某些原因,这种方法更好:
    1. 您的代码只能使用正确的类型进行编译。编译错误总是更好,然后是运行时错误 2. 可以显式调用该函数。如果您要从 Java 调用此代码,这可能非常重要。

    【讨论】:

    • 这就是我目前所做的。问题是它不能处理所有的可能性。例如,用户可能想要使用他们自己的类。如果可能的话,我想要一个可以处理任何类的解决方案。
    • val str=ObjectOperationResult("foo"); val i=str 这将编译为隐式转换 ObjectOperationResult => IntObjectOperationResult.toInt 提供,但由于转换 anyRefValyeOfStr.asInstanceOf[Int] 将在运行时失败。不是编译时安全的。
    【解决方案2】:

    一种方法是将类类型作为参数和条件传递。

    import reflect.runtime.universe._
    
    case class ObjectOperationResult( val value: AnyRef )
    
    object ObjectOperationResult {
        def result2T[T: TypeTag](c: Class[T], result: ObjectOperationResult): T = {
            c match {
                case s if typeOf[T] <:< typeOf[String] => result.value.toString.asInstanceOf[T]
                case _ => result.value.asInstanceOf[T]
            }
        }
    }
    

    你可以这样使用它:

    val a = ObjectOperationResult("hello")
    val b = ObjectOperationResult(new java.util.Date())
    
    ObjectOperationResult.result2T(classOf[String], a)
    res0: String = hello
    
    ObjectOperationResult.result2T(classOf[String], b)
    res1: String = Fri Jul 03 13:15:12 PDT 2015
    
    ObjectOperationResult.result2T(classOf[java.util.Date], b)
    res2: java.util.Date = Fri Jul 03 13:15:12 PDT 2015
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-24
      • 2011-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-20
      • 2016-01-14
      • 1970-01-01
      相关资源
      最近更新 更多