Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type casting using type parameter

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 to some type T. If the conversion fails, the method should return None. I am looking for something similar to this:

def convert[T](key: String): Option[T] = {
  val obj = someJavaMethod(key)
  // return Some(obj) if obj is of type T, otherwise None
}

convert[Int]("keyToSomeInt") // yields Some(1)
convert[String]("keyToSomeInt") // yields None

(How) Can this be achieved using Scala's reflection API? I am well aware that the signature of convert might have to be altered.

like image 635
Fynn Avatar asked Aug 17 '13 12:08

Fynn


People also ask

What is type casting in C?

Type casting is when you assign a value of one data type to another type. In C#, there are two types of casting: Implicit Casting (automatically) - converting a smaller type to a larger type size. char -> int -> long -> float -> double. Explicit Casting (manually) - converting a larger type to a smaller size type.

What is casting in Java with example?

Java Type Casting. Type casting is when you assign a value of one primitive data type to another type. In Java, there are two types of casting: Widening Casting (automatically) - converting a smaller type to a larger type size. byte -> short -> char -> int -> long -> float -> double.

How do I typecast a variable in typescript?

Type castings allow you to convert a variable from one type to another. In TypeScript, you can use the as keyword or <> operator for type castings. Type casting using the as keyword The following selects the first input element by using the querySelector () method:

What is type casting in Python?

There can be two types of Type Casting in Python – Implicit Type Casting; Explicit Type Casting; Implicit Type Conversion. In this, methods, Python converts data type into another data type automatically. In this process, users don’t have to involve in this process.


2 Answers

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
like image 146
Miles Sabin Avatar answered Sep 21 '22 12:09

Miles Sabin


That's what a ClassTag is 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.

like image 22
gourlaysama Avatar answered Sep 17 '22 12:09

gourlaysama