Контекст
Ради возможности менять конфиг для тестирования у меня есть трейт почти со всем кодом. Затем в классе case я пытаюсь передать конфигурацию. В моем тестировании у меня есть класс тестового случая.
Это работает (но это не та функциональность, которую я хочу)
trait Greeting(val name: String) {
def msg = s"How are you, $name"
}
class prodEnvClass extends Greeting("Production Env") {
println(msg)
}
class testEnvClass extends Greeting("Testing Env") {
println(msg)
}
Это не работает (но это функциональность, которую я хочу)
trait Greeting(val name: String) {
def msg = s"How are you, $name"
}
class prodEnvClass extends Greeting(myEnv) {
val myEnv = fetchProdEnv()
println(msg)
}
class testEnvClass extends Greeting(myEnv) {
val myEnv = fetchTestEnv()
println(msg)
}
Вопрос
Как передать параметр, созданный внутри тела класса case, в трейт? Код, который работает, не соответствует моему варианту использования. Я хочу использовать код внутри класса case, чтобы сделать ввод в черту.
Хотя я должен отметить, вы могли бы использовать имя метода в качестве параметра. Это простое решение, но я бы так не придумал.
Есть похожий пост, в котором та же функциональность нужна для другой цели: Расширить абстрактный класс Java в Scala
Кажется, вы смешиваете вызов функции с наследованием таким образом, который не должен работать.
Для вызова функции вы
что-то вроде этого:
def f(s: String) { println(s) }
f("hello (function invocation)")
При использовании наследования вы
что-то вроде этого:
trait C { def s: String; def m() = println(s) }
new C { val s = "hello (inheritance)"; m() }
В вашем коде вы, кажется, пытаетесь
myEnv
, переопределив его по-разному в двух подклассах (как вы сделали бы для наследования)Просто выберите один механизм. Если вы хотите наследование, сделайте наследование:
class MyEnv(val name: String)
trait Greeting {
def myEnv: MyEnv
def msg = s"hello ${myEnv.name}"
}
def fetchProdEnv() = new MyEnv("prod")
def fetchTestEnv() = new MyEnv("test")
class ProdEnvClass extends Greeting {
val myEnv = fetchProdEnv()
println(msg)
}
class TestEnvClass extends Greeting {
val myEnv = fetchTestEnv()
println(msg)
}
new ProdEnvClass() // "hello prod"
new TestEnvClass() // "hello test"
но не пытайтесь использовать две половинки (по половинке от каждого механизма), они так не смешиваются.
Вы не можете AFAIK. (кстати, я также не вижу
case class
в вашем коде). Как бы вы инициализировали это? Вам нужно инициализировать трейт, чтобы инициализировать класс, но вам также нужно инициализировать класс, чтобы инициализировать трейт? Тут же конфликт. Вы должны сделать класс final и иметь сопутствующий объект, инициализирующий класс по мере необходимости. Он может загрузить требуемый конфиг и передать его дальше. Вы можете использовать ciris для загрузки в соответствующих средах.