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.

Język programowania Scala Wydanie 2. Copyright © Grzegorz Balcerek 2016

Licencja Creative Commons

Ten utwór jest dostępny na licencji Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 Międzynarodowe.

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.