Indirect class membership query

If I have an object c of type Class[_] and object x of type Any can I ask at runtime whether x is an instance of the class c?

class AtomicType(c: Class[_]) {
  def typep(a:Any):Boolean = c.isA(a) /// this is wrong
}

I’m looking for something like the following which is wrong. For instance if c is class java.lang.Integer and x=3.

You can get the class of an object with the getClass method, and then either compare it for equality or use the Class#isAssignableFrom method to allow for subclasses.

For example:

class Foo
class Bar extends Foo

val foo: Any = new Foo
val bar: Any = new Bar

val fooClass: Class[_] = classOf[Foo]

foo.getClass == fooClass // true
bar.getClass == fooClass // false
fooClass.isAssignableFrom(foo.getClass) // true
fooClass.isAssignableFrom(bar.getClass) // true
1 Like

How about:

x.getClass == c
1 Like

You can do this using ClassTag.

import scala.reflect.ClassTag

final class AtomicType(c: Class[_]) {
  def typep(a: Any):Boolean =
    ClassTag(c).unapply(a).isDefined
}

You may even decide to use ClassTag all from a beginning instead of using Class.


Anyways, you probably already know this, but the need to do runtime class checks probably means a bad design.

No I don’t think I want to know if the class is exactly c. that will fail for example if x is an Integer, but c is a superclass of Integer.

c.isInstance(x)

I found this in some clojure code, which leads me to believe there may be an isInstance method on the java class object. I tried to look at the java code, but got lost very quickly.

(def
 ^{:arglists '([^Class c x])
   :doc "Evaluates x and tests if it is an instance of the class
    c. Returns true or false"
   :added "1.0"}
 instance? (fn instance? [^Class c x] (. c (isInstance x))))

Then I think you want

c.isAssignableFrom(x.getClass)

isInstanceOf does exist in Scala. But it takes a type parameter, not an instance of Class[_], so it’s only useful if the class you want to compare to can be determined at compile-time (and I would argue it’s then more natural in Scala to use pattern-matching).

Hence the use of Class#isAssignableFrom in my first example above. :wink:

I’m not sure why you prefer getting the class rather than just checking class membership. Is there something I’m not seeing? s.typep(x) returns true and s.typep(y) returns false.

val x = 100
val y = "hello"

case class AtomicType(c:Class[_]){
  def typep(a:Any):Boolean = c.isInstance(a)
}

val s = AtomicType(classOf[Number])

s.typep(x)
s.typep(y)

I missed that method. Class.isInstance is probably best.