简体   繁体   中英

Passing class name to super class constructor in Scala via reflection

How can I pass the name of a class to its super class constructor and is it even possible? I'm thinking about something like this:

class TestClass extends SuperTestRequiringName(TestClass.getClass.getName) {}

This would be better than passing the name as a hard-coded string because consistency is preserved during rename refactorings.

Even better would be the actual runtime class so I would get the name of a subclass if possible. But this doesn't work as well:

class TestClass extends SuperTestRequiringName(this.getClass.getName) {}

I'm not asking how to access the subclass name inside the super class at runtime in general. It is important that the class name is available as a super constructor argument so the super class can pass it along to its own super class (from a library I can't change).

class TestClass extends SuperTestRequiringName(classOf[TestClass].getName)

In Scala classOf[A] is the same as A.class in Java.

getClass is a method, which you only can call on instances of classes.

I'm not sure if I correctly understand your question or not but you can use ClassTag for this purpose. For example;

import scala.reflect._
class SuperTestRequiringName(name: String) {}
class TestClass extends SuperTestRequiringName(classTag[TestClass].runtimeClass.getName)

I hope it helps!

I don't think your problem has a good solution as is. The way JVM memory model works, you can't use this before the call to the base constructor, even to get your own class name. If the reason you inherit from the library's class is to re-use its functionality, rather than the need to actually use your classes in the same contexts the base class is used, I'd suggest replacing inheritance with composition which is the right solution for such a problem anyway. The code would go like this:

case class Wrapper(s: String)

class LibraryClass(val w: Wrapper) {
  def someUsefulStuff(n: Int): String = ???

  def someNotUsefulStuff(n: Int): String = ???
}

class Base() {
  private val delegate:LibraryClass = new LibraryClass(Wrapper(this.getClass.getName))

  // expose useful methods from the delegate
  // depending on logic maybe decorate them as protected
  def someUsefulStuff(n: Int): String = delegate.someUsefulStuff(n)
}

class LeafA extends Base

class LeafB extends Base

See this example online .

If you really need to inherit from the LibraryClass to be used in those contexts, you probably will have to make your subclasses pass the string explicitly as in @ygor solution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM