Scala промежуточный ранний инициализатор

Есть ли способ в scala использовать промежуточный ранний инициализатор?

Вот что я пытаюсь скомпилировать:

trait A { val valueA: Int = 0 }
trait B { 
  val valueB: Int 
  println(valueB)
}


class C extends A with { val valueB = valueA } with B

РЕДАКТИРОВАТЬ: ответ на вопрос Луиса

В scalatest фикстуры могут быть организованы с помощью конструкторов трейтов. Я хотел бы параметризовать одну субфикстуру и заранее инициализировать поле из суперфикстуры.

Вот еще один пример, который лучше относится к реальному масштабному случаю:

class Test extends FreeSpec {
  trait CommonFixture {
    val commonCaseValue: Int = 1
  }
  abstract trait SpecialCaseFixture {
    val specialCaseValue: Int
  }

  "special case test #1" in new CommonCaseFixture with { val specialCaseValue = commonCaseValue } with SpecialCaseFixture {
    // all fixtures fields are accessible here
  }
}

person montrivo    schedule 17.01.2020    source источник
comment
В соответствии с синтаксисом scala EarlyDefs должен стоять перед любым другим родительским классом или трейтом. - scala-lang.org/files /архив/спецификация/2.13/   -  person sarveshseri    schedule 17.01.2020
comment
Можете ли вы сказать нам, почему вы хотите этого? Возможно, есть лучшие способы добиться этого.   -  person Luis Miguel Mejía Suárez    schedule 17.01.2020


Ответы (2)


Просто переопределите его с помощью lazy val:

trait A { val valueA: Int = 100500 }
trait B {
  val valueB: Int
  println(valueB)
}
class C extends A with B { lazy val valueB = valueA } 
new C 
// prints 100500
person Dima    schedule 17.01.2020
comment
Он печатает 0, потому что это неинициализированное значение Int, попробуйте с другим целым числом. - person montrivo; 17.01.2020
comment
@montrivo ТЫ попробуй с другим целым числом :) - person Dima; 17.01.2020
comment
Плохо, я удалил ленивый модификатор, когда пробовал ваш пример. Так лениво.. :) Спасибо! - person montrivo; 17.01.2020
comment
Вот ветка форума scala на эту тему: scala-lang.org/old/node/ 6077 - person montrivo; 17.01.2020

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

class FixturesSpec extends FlatSpec with Matchers {
  case class FixtureA(x: Int = 42)
  case class FixtureB(y: Int = -11)

  trait CommonFixture {
    val commonCaseValue: Int = 1
  }
  trait SpecialCaseFixture {
    val specialCaseValue: Int
  }

  "traits" should "be fixtures" in new SpecialCaseFixture with CommonFixture  {
    override val specialCaseValue = commonCaseValue
    specialCaseValue should be (1)
  }

  "case classes" should "be fixtures" in new FixtureA(FixtureB().y)  {
    x should be (-11)
  }
}
person Mario Galic    schedule 17.01.2020
comment
В примере не решается проблема SpecialCaseFixture.specialCaseValue, которая недоступна во время инициализации. Если вы добавите оператор println в тело SpecialCaseFixture, он напечатает null. - person montrivo; 17.01.2020