Znalazłem błąd w moim kodzie scala, który mnie zastanawia. Poniżej znajduje się uproszczona wersja problemu.Metoda abstrakcyjna Scala ma wartość zerową w nadklasie, gdy jej podklasa implementuje za pomocą val?
W konstruktorze klasy abstrakcyjnej chcę sprawdzić kilka twierdzeń na temat metod abstrakcyjnych. W ten sposób, gdy tworzony jest obiekt podklasy, te potwierdzenia są sprawdzane, aby sprawdzić, czy wszystko jest zaimplementowane tak, jak powinno.
To idzie źle, gdy podklasa implementuje metody abstrakcyjne używając "val" Jednakże: kod
Scala:
abstract class A {
def aval : String
assert(aval != null, "aval == null")
assert(aval == "B", "aval: "+aval)
}
class B extends A {
def aval = "B"
}
class C extends A {
val aval = "B"
}
object VariousScalaTests {
def main(args : Array[String]) : Unit = {
val b = new B
val c = new C
}
}
Scala błąd:
Exception in thread "main" java.lang.AssertionError: assertion failed: aval == null
at scala.Predef$.assert(Predef.scala:92)
at A.<init>(VariousScalaTests.scala:4)
at C.<init>(VariousScalaTests.scala:12)
at VariousScalaTests$.main(VariousScalaTests.scala:19)
at VariousScalaTests.main(VariousScalaTests.scala)
Więc nie powiedzie u ostatnia linia kodu: "val c = new C". Klasa B działa idealnie, ale klasa C nie! Jedyna różnica polega na tym, że C implementuje aval używając "val" i B używając "def".
Moje pytanie, przede wszystkim, dlaczego ta różnica? Nie rozumiem, co się dzieje.
Czy istnieje sposób, aby działał tak, jak chcę w obu przypadkach w scala? Czy po prostu brakuje mi bardziej eleganckiego sposobu potwierdzania tego, co chcę w scala?
Twój kod Java wyjaśnia ładnie! Rozumiem teraz ... Rozważanie takich zachowań, jak "unikanie wywoływania wirtualnych metod od konstruktora" wydaje się dobrą radą. Z pewnością w scala, podobnie jak w kodzie java, jest o wiele bardziej jasne, co się dzieje. Poszukuję innego sposobu, aby elegancko sprawdzić podklasy w moim konkretnym przypadku, twój link może pomóc. Przynajmniej tajemnica tego błędu już minęła ;-) –