scala: как получить класс в своем собственном конструкторе - PullRequest
4 голосов
/ 27 сентября 2010

Мне нужен доступ к классу объекта, который создается в его собственном конструкторе (по разным подробным причинам, я не думаю, что он имеет отношение к моему вопросу).

Я хочу что-то вроде этого

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

для печати 3 ("Бар". Длина). Но это не так. Если приведенный выше код находится внутри какого-либо другого объекта, «this» относится к этому объекту. Если приведенный выше код не находится внутри какого-либо другого объекта (только в некотором пакете), компилятор жалуется на

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

УТОЧНЕНИЕ: я не могу изменить Foo, чтобы использовать val в его теле вместо его конструктора, потому что API Foo уже существует и является фиксированным (поэтому, да, i должен быть параметром конструктора). Ему нужен целочисленный аргумент во время конструктора, но это целое число может быть вычислено только с доступом к классу.

(Я знаю, что приведенный выше пример все еще глупый и вырожденный. Если людям все равно, я могу подробно объяснить, почему мне нужен класс в моем реальном проекте, http://code.google.com/p/factorie)

Конечно, класс создаваемого объекта известен компилятору и среде выполнения во время построения. С каким синтаксисом я могу его получить? (Нет ли такого синтаксиса? Если нет, я удивляюсь, почему. Я удивлен, что, кажется, не существует простого, стандартного способа получить это.)

Ответы [ 6 ]

8 голосов
/ 27 сентября 2010

Ленивый вал решает эту проблему:

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

Урожайность:

% scala Early
Early$Bar
2 голосов
/ 28 сентября 2010

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

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 голосов
/ 27 сентября 2010

Не уверен, возможно ли это чистым способом.Если вам нравятся хаки, вы можете сделать

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

Однако я настоятельно рекламирую против него!

1 голос
/ 28 сентября 2010

Как насчет

класс Bar расширяет Foo (classOf [Bar] .getName.length)

1 голос
/ 27 сентября 2010

Вы должны будете объяснить свою мотивацию желания сделать это.Должно ли имя быть параметром конструктора Foo или это может быть абстрактный член?Должно ли это быть val или def делать.

Вы можете сделать это

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

и new Bar().name даст Бар

Но я подозреваю, что если ваша истинная мотивация известна, то есть лучший способчто вы действительно хотите.

0 голосов
/ 27 сентября 2010

Что по этому поводу:

  class Foo(otherName: Option[String] = None) {
    val name = otherName.getOrElse(this.getClass.getName)
  }
  class Bar extends Foo()
  val b = new Bar
  println(b.name)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...