В Scala вы можете создать экземпляр с ссылкой на другой класс или черту? - PullRequest
2 голосов
/ 14 марта 2012

Я хочу создать экземпляр с переменной, обозначающей некоторую черту, подобную приведенной ниже, которая выдает ошибку.Есть ли способ сделать это в Scala?

var traitRefer = classOf[SomeTrait]
var a = new SomeClass() with traitRefer

Ответы [ 3 ]

7 голосов
/ 14 марта 2012

Я не думаю, что есть способ сделать это, кроме рефлексии, потому что это небезопасно.Что вы можете сделать, это создать экземпляр с определенной чертой, смешанной в сопоставлении с образцом.Например,

kind match {
  case "Foo" => new SomeClass with Foo
  case "Bar" => new SomeClass with Bar
}
3 голосов
/ 14 марта 2012

Отличный вопрос! Что вы упускаете в своем понимании, так это то, что происходит во время компиляции по сравнению с тем, что происходит во время выполнения .

Когда компилятор Scala встречает выражение, такое как new Foo with Bar, во время компиляции он генерирует анонимный внутренний класс, который по существу совпадает с class Anonymous extends Foo with Bar. Затем компилятор делает всю свою магию о наращиваемых чертах и ​​о том, что - не, чтобы произвести вывод, который вы хотите. Базовый класс и расширенные черты должны быть определены во время компиляции; Вы не можете определить их во время выполнения. *

Поскольку черта, которую вы хотите добавить, неизвестна до времени выполнения, компилятор не знает, что генерировать для анонимного класса.

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

(*) То, что вы можете сделать во время выполнения, это сгенерировать байт-код для нового класса. Есть множество способов сделать это, включая встраивание компилятора Scala. Это, однако, не для финт сердца. Конечно, есть более простой способ выполнить то, что вы пытаетесь сделать.

2 голосов
/ 14 марта 2012

Я думаю, что это невозможно (исключить рефлексию). Подробнее здесь . Вы можете сделать это:

type Ref = SomeTrait
var a = new SomeClass with Ref

Но я думаю, что это не то, что вы хотите

...