5

Is there any way to match just on generic type passed in function? I'd like to do:

def getValue[T](cursor: Cursor, columnName: String): T = {
    val index = cursor.getColumnIndex(columnName)
    T match {
        case String => cursor.getString(index)
        case Int => cursor.getInteger(index)
 }

I thought about something like classOf or typeOf, but none of them is acceptable for just types, but objects.

My idea was also to create some object of type T and then check its type, but I think there can be a better solution.

Kamil Lelonek
  • 14,592
  • 14
  • 66
  • 90

1 Answers1

6

You could use ClassTag.

val string = implicitly[ClassTag[String]]
def getValue[T : ClassTag] =
  implicitly[ClassTag[T]] match {
    case `string` => "String"
    case ClassTag.Int => "Int"
    case _ => "Other"
  }

Or TypeTag:

import scala.reflect.runtime.universe.{TypeTag, typeOf}

def getValue[T : TypeTag] =
  if (typeOf[T] =:= typeOf[String])
    "String"
  else if (typeOf[T] =:= typeOf[Int])
    "Int"
  else
    "Other"

Usage:

scala> getValue[String]
res0: String = String

scala> getValue[Int]
res1: String = Int

scala> getValue[Long]
res2: String = Other

If you are using 2.9.x you should use Manifest:

import scala.reflect.Manifest
def getValue[T : Manifest] =
  if (manifest[T] == manifest[String])
    "String"
  else if (manifest[T] == manifest[Int])
    "Int"
  else
    "Other"
senia
  • 37,745
  • 4
  • 88
  • 129
  • @PatrykĆwiek: It's possible to store type information in some addition field, but it'll break java compatibility. There is no way to avoid type erasure in types from java. – senia Jul 09 '13 at 09:35
  • I know, I know. Just wishful thinking. Maybe I'm just a little bit spoiled by C#/F#. – Patryk Ćwiek Jul 09 '13 at 09:36
  • 2
    @senia you can write `typeOf[String]` instead of `implicitly[TypeTag[String]].tpe` (import `typeOf` from `universe`) – 0__ Jul 09 '13 at 10:38
  • @0__, @senia `error: object runtime is not a member of package reflect` – Kamil Lelonek Jul 09 '13 at 12:17
  • 1
    @squixy: `scalaVersion := "2.10.2"`. In 2.9.x you should use [`Manifest`](http://www.scala-lang.org/api/current/index.html#scala.reflect.Manifest). – senia Jul 09 '13 at 12:24