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