John Mullins
John Mullins

Reputation: 1101

Cast some object with the help of its Type

Is it possible to cast some object with the help of its Type. For example:

import scala.reflect.api.Types

val t: Types#Type = ...// real type of the object o below
println(t)            // out: com.project.Event[java.lang.String]
val o: Any = ...       // some object which has above type


val e: com.project.Event[java.lang.String] = cast(o, t)

def cast(o: Any, t: Type) = ???

Upvotes: 0

Views: 125

Answers (2)

dk14
dk14

Reputation: 22374

If you use exactly Type (not TypeTag[T]) - in general case no, because the instance of Type doesn't store any information in compile-time: there is no type-level members/parameters storing that info.

So if you use Type in runtime - there is no way to know which compile-time type it's corresponding to (what is the return type of your cast function? _? :) ).

So your cast would have to have a signature like:

def cast[T](o: Any, t: Type): T = o.asInstanceOf[T]

in which case Type doesn't really help as (unlike TypeTag[T]) it doesn't provide anything for type inference of T. Even conversion from Type to TypeTag[T] obviously requires you to specify type explicitly, like cast[String] and so on.

The only thing Type can be used for is to check if o actually corresponds t:

def cast[T](o: Any, t: Type): Option[T] = 
  if (mirror.reflect(o).symbol == t.typeSymbol) Some(o.asInstanceOf[T]) else None

up to something like:

def cast[T: TypeTag](o: Any, t: Type): Option[T] = 
  if (mirror.reflect(o).symbol == t.typeSymbol && typeOf[T] =:= t)
    Some(o.asInstanceOf[T]) 
  else None

One obvious exception is when you obtained a Type inside a macro, so you can compose a tree with correct asInstanceOf in compile-time:

https://groups.google.com/forum/#!topic/scala-user/3YF_98W9eSE

Upvotes: 1

chengpohi
chengpohi

Reputation: 14217

I think you can use TypeTag for holding the type info and cast it to the target type, like:

import scala.reflect.runtime.universe._

// get TypeTag by typeTag[A]
val t: TypeTag[com.project.Event[java.lang.String]] = typeTag[com.project.Event[java.lang.String]]

//cast with typeTag
val r:com.project.Event[java.lang.String]  = cast(o, t)
def cast[A](o: Any, t: TypeTag[A]) = o.asInstanceOf[A]

if you can't get TypeTag directly, maybe you want to convert the Type to TypeTag:

Get a TypeTag from a Type?

Upvotes: 0

Related Questions