Type casting using type parameter

前端 未结 2 1245
孤独总比滥情好
孤独总比滥情好 2020-12-16 01:46

Given is a Java method that returns java.lang.Objects for a given string. I\'d like to wrap this method in a Scala method that converts the returned instances t

相关标签:
2条回答
  • 2020-12-16 02:07

    You could try shapeless's Typeable,

    scala> import shapeless._ ; import syntax.typeable._
    import shapeless._
    import syntax.typeable._
    
    scala> def someJavaMethod(key: String): AnyRef =
         |   key match {
         |     case "keyToSomeInt" => 23.asInstanceOf[AnyRef]
         |     case "keyToSomeString" => "foo"
         |   }
    someJavaMethod: (key: String)AnyRef
    
    scala> def convert[T: Typeable](key: String): Option[T] =
         |   someJavaMethod(key).cast[T]
    convert: [T](key: String)(implicit evidence$1: shapeless.Typeable[T])Option[T]
    
    scala> convert[Int]("keyToSomeInt")
    res0: Option[Int] = Some(23)
    
    scala> convert[String]("keyToSomeString")
    res1: Option[String] = Some(foo)
    
    scala> convert[String]("keyToSomeInt")
    res2: Option[String] = None
    
    scala> convert[Int]("keyToSomeString")
    res3: Option[Int] = None
    
    0 讨论(0)
  • 2020-12-16 02:21

    That's what a ClassTag if for:

    import reflect.ClassTag
    
    def convert[T : ClassTag](key: String): Option[T] = {
      val ct = implicitly[ClassTag[T]]
      someJavaMethod(key) match {
        case ct(x) => Some(x)
        case _ => None
      }
    }
    

    It can be used as an extractor to test and cast to the proper type at the same time.

    Example:

    scala> def someJavaMethod(s: String): AnyRef = "e"
    someJavaMethod: (s: String)AnyRef
    
    [...]
    
    scala> convert[Int]("key")
    res4: Option[Int] = None
    
    scala> convert[String]("key")
    res5: Option[String] = Some(e)
    

    Edit: note however that a ClassTag does not automatically unbox boxed primitives. So, for example, convert[Int]("a") would never work, because the java method returns AnyRef, it would have to be convert[java.lang.Integer]("a"), and so on for other primitive types.

    Miles's answer with Typeable seems to take care of those edge cases automatically.

    0 讨论(0)
提交回复
热议问题