jqno
jqno

Reputation: 15520

Scala reflection: can I see if something is a (case) object?

Is there a way in Scala to see if a class was defined as an object?

def isObject(c: Class[_]): Boolean = ???

object X
class Y

val x = X
val y = new Y

isObject(x.getClass) == true
isObject(y.getClass) == false

Upvotes: 1

Views: 543

Answers (2)

ygor
ygor

Reputation: 1756

Using scala-reflect, following seems to work:

object ObjectReflection extends App {

  import scala.reflect.runtime.universe._

  def isObject[T](x: T)(implicit tag: TypeTag[T]): Boolean = PartialFunction.cond(tag.tpe) {
    case SingleType(_, _) => true
  }

  object AnObject
  case object ACaseObject
  class AClass
  case class ACaseClass(i: Int)
  trait ATrait

  println("new AClass     " +  isObject(new AClass))
  println("ACaseClass(42) " +  isObject(ACaseClass(42)))
  println("new ATrait {}  " +  isObject(new ATrait {}))
  println("AnObject       " +  isObject(AnObject))
  println("ACaseObject    " +  isObject(ACaseObject))

}

Prints:

new AClass     false
ACaseClass(42) false
new ATrait {}  false
AnObject       true
ACaseObject    true

Depends on:

libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value

Upvotes: 4

Alexey Romanov
Alexey Romanov

Reputation: 170713

As a first approximation, you can do

def isObject(c: Class[_]): Boolean = c.getName.endsWith("$")

because the anonymous class created for a singleton object y has name y$, and the usual anonymous classes (such as new AnyRef {}) end in $<number> instead.

But it's legal to create class y$ as well, which would give a false positive; such names are rare in practice, though.

Using scala-reflect should allow a more precise answer.

Upvotes: 2

Related Questions