Scala: how to get a class in your own constructor

I need access to the class of the object, which is built in its own constructor (for various detailed reasons, which, it seems to me, are not relevant to my question).

I need something like this

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

to print 3 ("Bar" .length). But this is not so. If the code above is inside some other object, "this" refers to this object. If the code above is not inside any other object (only in some package), the compiler complains about

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

CLARIFICATION: I cannot change Foo to use val in my body instead of my constructor, because the Foo API already exists and is fixed (so yes, I have to be a constructor parameter). It needs an integer argument at the time of the constructor, but this integer can only be computed with access to the class.

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

Of course, the class of the created object is known to the compiler and the runtime at build time. What syntax can I get it with? (Is there such a syntax? If not, I wonder why. I'm surprised it doesn't seem like a simple, standard way to get this.)

+4
source share
6 answers

You will need to explain your motivation for wanting to do this. Should the name be a parameter of the Foo constructor or can it be an abstract element? It must be val or def will do.

You can do it

 class Foo(val name: String) class Bar extends Foo("") { override val name = getClass.getName } 

and new Bar().name will give Bar

But I suspect that if your true motivation is known, then there is a better way to do what you really want.

+1
source

lazy shaft 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) } } 

Productivity:

 % scala Early Early$Bar 
+8
source

Not sure if this is possible in its purest form. If you like hacks, you can do

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

However, I strongly advertise it!

+2
source

This seems to satisfy your requirements without using the lazy val value and without changing the base class:

 scala> class Base(val name: String) defined class Base scala> class Derived extends Base(classOf[Derived].getName) defined class Derived scala> new Derived name res0: String = Derived 
+2
source

What about

class Bar extends Foo (classOf [Bar] .getName.length)

+1
source

How about this:

  class Foo(otherName: Option[String] = None) { val name = otherName.getOrElse(this.getClass.getName) } class Bar extends Foo() val b = new Bar println(b.name) 
0
source

All Articles