Por que usar val simples em classes não finais

Se a classe não for final, ela pode ser estendida.

Existem duas possibilidades para valores: pode ser anulada e deve ser preguiçosa para ela, pode não ser anulada e deve ser final.

Se val é final - você pode assumir que todos os cálculos sobre ele funcionariam através da hierarquia de classes. Se val puder ser anulado, você deve declarar que é preguiçoso para não ser quebrado após a extensão. Você pode deixar val plain e isso não dá garantias de que seria estendido no caminho certo.

Quais casos de uso implicam o uso de valores simples?

Exemplo de falha de inicialização de classe sem valores lazy

abstract class A {
  lazy val x1 : String = throw new Exception()
  val x2 : String = "mom"
  val x3 : String = x1 + ", " + x2
  println("A: " + x3)
}
class B extends A {
  override lazy val x1: String = "hello"
  println("B: " + x3)
}
class C extends B {
  override val x2: String = "dad"
  println("C: " + x3)
}

testando:

scala> new B
A: hello, mom
B: hello, mom
res8: B = B@7e2bd615

funciona, mas outras subclasses quebraram a funcionalidade já existente

scala> new C
A: hello, null
B: hello, null
C: hello, null
res5: C = C@52a53948

definindo lazy em x2 corrige o caso:

abstract class A {
  lazy val x1 : String = throw new Exception()
  lazy val x2 : String = "mom"
  val x3 : String = x1 + ", " + x2
  println("A: " + x3)
}
class B extends A {
  override lazy val x1: String = "hello"
  println("B: " + x3)
}
class C extends B {
  override lazy val x2: String = "dad"
  println("C: " + x3)
}

ordem de inicialização correta:

scala> new C
A: hello, dad
B: hello, dad
C: hello, dad
res6: C = C@5e970110

questionAnswers(1)

yourAnswerToTheQuestion