0

Suppose I have a non-sealed trait A and need a function convert[T <: A]: A => Option[T]:

def convert[T <: A](a: A): Option[T] = // don't compile
  if (a is instance of T) then Some(a) else None 

How would you suggest implement that convert ?

P.S I don't like reflection but need to deal with legacy, which uses it.

Michael
  • 41,026
  • 70
  • 193
  • 341
  • 2
    You could use `ClassTag`, see [this answer](http://stackoverflow.com/a/18136667/406435). `def convert[T <: A : ClassTag](a: A) = {val clazz = implicitly[ClassTag[T]].runtimeClass; if (clazz.isInstance(a)) Some(a.asInstanceOf[T]) else None}` – senia Mar 30 '15 at 12:00
  • @senia Why `Some(a.asInstanceOf[T])` but not just `Some(a)` ? – Michael Mar 30 '15 at 12:32
  • type of `a` is `A`, so type of `Some(a)` is `Some[A]`, not `Some[T]` – senia Mar 30 '15 at 12:43
  • @senia Yes, but did not we check that `a` is of type `T` ? – Michael Mar 30 '15 at 12:47
  • @senia What if I replace `if (clazz.isInstance(a)) ` with `clazz == a.getClass` ? Does it work the same ? – Michael Mar 30 '15 at 12:49
  • No. `a` could be an instance of subtype of `T`. In this case `a` is instance of `T`, but class of `a` is not `T`. – senia Mar 30 '15 at 12:53

1 Answers1

2

Rather than isInstance, you can use the ClassTag in a match expression, which is slightly clearer:

def convert[T <: A](a: A)(implicit ct: ClassTag[T]) = a match {
  case ct(t) => Some(t)
  case _ => None
}
lmm
  • 17,386
  • 3
  • 26
  • 37