5.13. Nadpisywanie różnych rodzajów składowych
Składowe klasy definiowane za pomocą słów kluczowych val, var i def należą do tej samej przestrzeni nazw. Można sobie zatem zadać pytanie o możliwość ich wzajemnego nadpisywania przy dziedziczeniu.
W przypadku zmiennych zdefiniowanych w klasie nadrzędnej reguła jest prosta — nie mogą być nadpisane ani przez inną zmienną, ani przez metodę, ani przez wartość niezmienną.
scala> class A { var a = 1 }
defined class A
scala> class B extends A { override val a = 2 }
<console>:11: error: overriding variable a in class A of type Int;
value a cannot override a mutable variable
class B extends A { override val a = 2 }
^
scala> class B extends A { override def a = 2 }
<console>:11: error: overriding variable a in class A of type Int;
method a cannot override a mutable variable
class B extends A { override def a = 2 }
^
scala> class B extends A { override var a = 2 }
<console>:11: error: overriding variable a in class A of type Int;
variable a cannot override a mutable variable
class B extends A { override var a = 2 }
^
Wartości niezmienne zdefiniowane w klasie nadrzędnej mogą być nadpisane przez inną wartość niezmienną, ale nie przez metodę lub zmienną.
scala> class C { val c = 1 }
defined class C
scala> class D extends C { override val c = 2 }
defined class D
scala> class D extends C { override def c = 2 }
<console>:11: error: overriding value c in class C of type Int;
method c needs to be a stable, immutable value
class D extends C { override def c = 2 }
^
scala> class D extends C { override var c = 2 }
<console>:11: error: overriding value c in class C of type Int;
variable c needs to be a stable, immutable value
class D extends C { override var c = 2 }
^
Bezparametrowe metody zdefiniowane w klasie nadrzędnej mogą być zastąpione w klasie podrzędnej zarówno przez inną metodę zdefiniowaną przy użyciu def, jak i przez wartość niezmienną zdefiniowaną przy użyciu val.
scala> class E { def e = 1 }
defined class E
scala> class F extends E { override val e = 2 }
defined class F
scala> class F extends E { override def e = 2 }
defined class F
scala> class F extends E { override var e = 2 }
<console>:11: error: method e_= overrides nothing
class F extends E { override var e = 2 }
^
W przypadku nadpisywania metody przez zmienną definiowaną poprzez var w ostatnim przykładzie, kompilator nie pozwala na nadpisanie metody e, gdyż definicja zmiennej w podklasie ma modyfikator override, a tworzona przy okazji definicji zmiennej metoda e_= nie nadpisuje niczego. A gdyby taka metoda istniała w nadklasie? Taką sytuację ilustruje następny przykład.
scala> class E2 { def e = 1; def e_=(x: Int) = () }
defined class E2
scala> class F2 extends E2 { override var e = 2 }
defined class F2
scala> val f2 = new F2
f2: F2 = F2@1cd168a
scala> f2.e
res0: Int = 2
scala> f2.e = 4
f2.e: Int = 4
scala> f2.e
res1: Int = 4
Nadpisanie metod e oraz e_= zmienną e udało się.
![]() | W przypadku nadpisywania metod mających pustą listę parametrów lub nie mających jej wcale, obowiązują dodatkowe zasady, które są opisane w punkcie 7.9. Więcej informacji o nadpisywaniu składowych znajduje się w punkcie 9.9. |

