5.14. Klasy abstrakcyjne

W języku Scala można definiować klasy abstrakcyjne. Takie klasy mogą mieć zadeklarowane, ale niezdefiniowane składowe, nazywane abstrakcyjnymi. Klasa definiowana jako abstrakcyjna musi posiadać modyfikator abstract przed słowem kluczowym class. Natomiast składowe klasy, które nie posiadają definicji, nie poprzedza się modyfikatorem abstract. Klasa AbstractHello, z pliku AbstractHello.scala, definiuje cztery abstrakcyjne składowe.

Plik AbstractHello.scala:
abstract class AbstractHello {
  type T
  val hello: String
  var name: T
  def greet
}

Nie jest możliwe utworzenie instancji klasy abstrakcyjnej.

scala> new AbstractHello
<console>:11: error: class AbstractHello is abstract; cannot be instantiated
       new AbstractHello
       ^

Błędem jest próba definicji klasy, która ma niezdefiniowaną składową, ale nie ma modyfikatora abstract.

scala> class A { def a }
<console>:10: error: class A needs to be abstract, since method a is not defined
       class A { def a }
             ^

Natomiast sytuacja odwrotna jest prawidłowa — można zdefiniować abstrakcyjną klasę, której wszystkie składowe są zdefiniowane. Mimo że taka klasa ma wszystkie składowe zdefiniowane, nie można utworzyć jej instancji.

scala> abstract class B { def b = "hi" }
defined class B

scala> new B
<console>:12: error: class B is abstract; cannot be instantiated
       new B
       ^

Klasa, która dziedziczy z klasy abstrakcyjnej, ale nie definiuje wszystkich jej abstrakcyjnych składowych, musi być również oznaczona modyfikatorem abstract, nawet jeśli nie wprowadza nowych, niezdefiniowanych składowych.

scala> abstract class C { val c : Int }
defined class C

scala> abstract class D extends C
defined class D

scala> class E extends C
<console>:11: error: class E needs to be abstract, since value c in class C of type Int is not defined
       class E extends C
             ^

Klasa, która dziedziczy z klasy abstrakcyjnej, ale która nie wprowadza, ani nie dziedziczy żadnych niezdefiniowanych składowych, może być pozbawiona modyfikatora abstract. Taka klasa nie jest abstrakcyjna i można tworzyć jej instancje.

scala> abstract class F
defined class F

scala> class G extends F
defined class G

scala> new G
res2: G = G@f9fcb2

W klasie, w której są nadpisywane abstrakcyjne składowe, nie trzeba ich definicji poprzedzać słowem kluczowym override, ale można to zrobić. Innymi słowy, w tych przypadkach słowo kluczowe override jest opcjonalne.

Plik AbstractHelloSubclasses.scala:
class Hello1 extends AbstractHello {
  type T = String
  val hello = "Hello"
  var name: T = "Peter"
  def greet = hello + " " + name
}
class Hello2 extends AbstractHello {
  override type T = String
  override val hello = "Hello"
  override var name: T = "Peter"
  override def greet = hello + " " + name
}

Obydwie definicje klas z pliku AbstractHelloSubclasses.scala są prawidłowe i kompilują się.

$ scalac AbstractHello.scala AbstractHelloSubclasses.scala

$

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.