Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pattern-match Class[X] for different X?

Tags:

types

scala

I want to check the type of the parameters of a method, but I don't know the best way to do this. See my code:

class X {
    def x(a: Int, b: String) {}
}

val methods = classOf[X].getDeclaredMethods
methods map { m =>
    m.getParameterTypes.toList map { t =>
        println(t.getName)
        // I don't know how to write the following
        if ( the type of t is Int) { do something} 
        else if( the type of t is String ) { do something}
        else { }
    }
}

Please note the comment in the code. I don't know how to check the types in scala way.

I've tried:

t match {
    case _:String => println("### is a string")
    case _:Int => println("### is an int")
    case _ => println("### ?")
}

But it can't be compiled.

I can use java-way to check:

if (t.isAssignableFrom(classOf[String])) // do something
else if(t.isAssignableFrom(classOf[Int])) // do something
else {}

It seems we should use it in scala, right?


UPDATE:

If I want to use match, I should write like this:

t match {
     case i if i.isAssignableFrom(classOf[Int]) => println("### is an Int")
     case s if s.isAssignableFrom(classOf[String]) => println("### is a String")
     case _ => println("###?")
}

Is it the best answer?

like image 892
Freewind Avatar asked Mar 04 '11 08:03

Freewind


2 Answers

I could make it work with t as a type by defining the cases as constants. It wouldn't compile with the class literals as the case expression. Try:

val S = classOf[String]
val I = classOf[Int]
t match {
    case S => println("### is a string")
    case I => println("### is an int")
    case _ => println("### ?")
}
like image 194
richj Avatar answered Nov 18 '22 04:11

richj


You can use ClassManifest.fromClass to correctly handle the coercion of primitives to AnyVals, and any other such troubles you might have encountering boxed vs unboxed types when getting funky with reflection.

Like this:

import reflect.ClassManifest

class Wibble { def method(a:Int, b: String) = () }

for(method <- classOf[Wibble].getDeclaredMethods; paramType <- method.getParameterTypes) {
  ClassManifest.fromClass(paramType) match {
    case m if m <:< ClassManifest.Int => println("Interiffic")
    case m if m <:< ClassManifest.Float => println("Floaty, like butterflies")
    case m if m <:< ClassManifest.Double => println("Or Quits...")
    //todo: all the other AnyVal types...
    case m if m <:< classManifest[String] => println("bleeding edge physics, yeah baby!")
    //...and a default condition
  }
} 
like image 42
Kevin Wright Avatar answered Nov 18 '22 04:11

Kevin Wright