Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scala: How to get the class in its own constructor

I need access to the Class of the object being constructed in its own constructor (for various detailed reasons I don't think are relevant to my question).

I want something like this

class Foo(val i:Int)
class Bar extends Foo(this.getClass.getName.length)
val b = new Bar
println(b.i)

to print 3 ("Bar".length). But it doesn't. If the code above is inside some other object, "this" refers to that object. If the code above is not inside some other object (just in some package), the compiler complains with

error: this can be used only in a class, object, or template
class Bar extends Foo(this.getClass.getName)
                      ^

CLARIFICATION: I can't change Foo to use a val in its body instead of its constructor because Foo's API already exists and is fixed (so, yes, i must be a constructor parameter). It needs an integer argument at constructor time, but that integer can only be calculated with access to the Class.

(I know the example above is still silly and degenerate. If people care, I can explain in detail why I need the class in my real project, http://code.google.com/p/factorie)

Surely, the class of the object being constructed is known to the compiler and runtime during construction. With what syntax can I get it? (Is there no such syntax? If not, I wonder why. I'm surprised it there doesn't seem to be a simple, standard way to get this.)

like image 394
mccallum Avatar asked Dec 10 '22 13:12

mccallum


2 Answers

A lazy val solves this problem:

object Early
{
    abstract class Foo { val name: String }

    class Bar extends Foo { lazy val name = getClass.getName }

    def
    main(args: Array[String]): Unit = {
        val b = new Bar
        println(b.name)
    }
}

Yields:

% scala Early
Early$Bar
like image 141
Randall Schulz Avatar answered Jan 17 '23 21:01

Randall Schulz


Not sure whether this is possible in a clean way. If you like hacks you could do

class Bar extends Foo((new Exception).getStackTrace.apply(0).getClassName)

However I strongly advertise against it!

like image 36
michid Avatar answered Jan 17 '23 19:01

michid