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. |