6.5. Modyfikatory abstract override

Plik AbstractOverride1.scala zawiera definicje cechy AbstractGreeting, zawierającej abstrakcyjną metodę greeting oraz klasy HelloGreeting, rozszerzającej tę cechę i implementującej metodę greeting.

Plik AbstractOverride1.scala:
trait AbstractGreeting {
  def greeting: String
  def greet = println(greeting)
}
class HelloGreeting extends AbstractGreeting {
  override def greeting = "Hello"
}

Wywołanie metody greet na instancji klasy HelloGreeting powoduje wyświetlenie pozdrowienia „Hello”.

scala> val hello1 = new HelloGreeting
hello1: HelloGreeting = HelloGreeting@852c0f

scala> hello1.greet
Hello

Cecha ExclamationGreeting, która jest zdefiniowana w pliku AbstractOverride2.scala, rozszerza cechę AbstractGreeting. Metoda greeting nadpisuje abstrakcyjną metodę z AbstractGreeting, jednocześnie odwołując się do metody o tej nazwie poprzez wyrażenie super.greeting.

Plik AbstractOverride2.scala:
trait ExclamationGreeting extends AbstractGreeting {
  def greeting = super.greeting + "!"
}

Próba kompilacji pliku AbstractOverride2.scala powoduje wystąpienie błędu.

$ scalac AbstractOverride2.scala
AbstractOverride2.scala:2: error: method greeting in trait AbstractGreeting is accessed from super. It may not be abstract unless it is overridden by a member declared `abstract' and `override'
  def greeting = super.greeting + "!"
                       ^
one error found

W takiej sytuacji wymagane jest zastosowanie modyfikatorów abstract i override. Prawidłowa definicja znajduje się w pliku AbstractOverride3.scala.

Plik AbstractOverride3.scala:
trait ExclamationGreeting extends AbstractGreeting {
  abstract override def greeting = super.greeting + "!"
}

Modyfikatory abstract override mogą być zastosowane tylko w przypadku definiowania składowych w cechach. Nie można ich stosować w definicjach zwykłych klas. Próba zdefiniowania takiej klasy znajduje się w pliku AbstractOverride4.scala.

Plik AbstractOverride4.scala:
class ExclamationGreetingClass extends AbstractGreeting {
  abstract override def greeting = super.greeting + "!"
}

Jego kompilacja powoduje wystąpienie błędu.

$ scalac AbstractOverride4.scala
AbstractOverride4.scala:2: error: `abstract override' modifier only allowed for members of traits
  abstract override def greeting = super.greeting + "!"
                        ^
one error found

Instancja klasy HelloGreeting, rozszerzonej o cechę ExclamationGreeting, jest tworzona w poniższym poleceniu.

scala> val hello2 = new HelloGreeting with ExclamationGreeting
hello2: HelloGreeting with ExclamationGreeting = $anon$1@131522b

scala> hello2.greet
Hello!

Wyrażenie hello2.greet wywołuje metodę greet, która wypisuje na ekran rezultat wywołania metody greeting. Cecha ExclamationGreeting znajduje się przed klasą HelloGreeting w porządku linearyzacji klasy, której instancją jest hello2. Wobec tego metoda greet wywołuje metodę greeting z tej właśnie cechy, a ta metoda zwraca wartość wyrażenia super.greeting z dodanym napisem „!”. Wyrażenie super.greeting powoduje odwołanie się do metody greeting, która jest zdefiniowana w HelloGreeting i która zwraca łańcuch „Hello”. Dlatego rezultatem wywołania metody greet jest wyświetlenie napisu „Hello!”.

Plik AbstractOverride5.scala definiuje inną cechę dziedziczącą z AbstractGreeting i rozszerzającą metodę greeting z odwołaniem do super.greeting.

Plik AbstractOverride5.scala:
trait DoubleGreeting extends AbstractGreeting {
  abstract override def greeting =
    super.greeting + " " + super.greeting
}

Tym razem rezultatem wywołania metody greet na instancji klasy powstałej przez dodanie cechy DoubleGreeting do klasy HelloGreeting jest wyświetlenie napisu „Hello Hello”. Mechanizm działania jest podobny do opisanego wcześniej.

scala> val hello3 = new HelloGreeting with DoubleGreeting
hello3: HelloGreeting with DoubleGreeting = $anon$1@1367418

scala> hello3.greet
Hello Hello

Mając cechy DoubleGreeting i ExclamationGreeting oraz klasę HelloGreeting można tworzyć różne ich kombinacje.

scala> val hello4 = new HelloGreeting with DoubleGreeting with ExclamationGreeting
hello4: HelloGreeting with DoubleGreeting with ExclamationGreeting = $anon$1@33c17b

scala> hello4.greet
Hello Hello!

scala> val hello5 = new HelloGreeting with ExclamationGreeting with DoubleGreeting
hello5: HelloGreeting with ExclamationGreeting with DoubleGreeting = $anon$1@1655d3e

scala> hello5.greet
Hello! Hello!

Analizę działania tych przykładów pozostawiam czytelnikowi.

Specyfikacja języka Scala opisuje modyfikator abstract override w punkcie 5.2.4.

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.