I can't think of any way to do it with no extra overhead. You could do it with companion objects, however, and a couple of extra pieces of work:
object Example {
trait Discovery {
def companion: Discovered
def className: String = companion.className
}
trait Discovered extends Discovery {
override lazy val className = {
println("Getting class name!") // To see how many times we're called
this.getClass.getSuperclass.getName
}
}
class Test extends Discovery {
def companion = Test
}
object Test extends Test with Discovered {}
}
And here we see that this works:
scala> val a = new Example.Test
a: Example.Test = Example$Test@17e4c97
scala> val b = a.className
Getting class name!
b: String = Example$Test
scala> val c = a.className
c: String = Example$Test
but it comes at rather a price: you need to not only decorate the class with Discovery but also implement the companion method and write the companion object (which need not have the same name, incidentally) for every class.