Передача имени класса конструктору суперкласса в Scala с помощью отражения - PullRequest
0 голосов
/ 07 января 2019

Как я могу передать имя класса его конструктору суперкласса, и возможно ли это вообще? Я думаю о чем-то вроде этого:

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

Это было бы лучше, чем передавать имя в виде жестко закодированной строки, потому что согласованность сохраняется во время рефакторинга переименования.

Еще лучше было бы фактический класс времени выполнения, поэтому я бы получил имя подкласса, если это возможно. Но это тоже не работает:

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

Я вообще не спрашиваю, как получить доступ к имени подкласса внутри суперкласса во время выполнения. Важно, чтобы имя класса было доступно в качестве аргумента супер-конструктора, чтобы суперкласс мог передать его своему собственному суперклассу (из библиотеки, которую я не могу изменить).

Ответы [ 3 ]

0 голосов
/ 07 января 2019

Я не уверен, правильно ли я понял ваш вопрос или нет, но вы можете использовать ClassTag для этой цели. Например;

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

Надеюсь, это поможет!

0 голосов
/ 07 января 2019

Не думаю, что у вашей проблемы есть хорошее решение как есть. Как работает модель памяти JVM, вы не можете использовать 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

См. Этот пример онлайн .

Если вам действительно нужно наследовать от LibraryClass для использования в этих контекстах, вам, вероятно, придется заставить ваши подклассы передавать строку явно, как в @ygor solution.

0 голосов
/ 07 января 2019
class TestClass extends SuperTestRequiringName(classOf[TestClass].getName)

В Scala classOf[A] совпадает с A.class в Java.

getClass - это метод, который вы можете вызывать только для экземпляров классов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...