6.7. Typ własny

W punkcie 5.10 pokazana została możliwość zdefiniowania aliasu klasy poprzez wprowadzenie na początku definicji jej ciała parametru, po którym umieszcza się podwójną strzałkę. Taki parametr klasy lub cechy może być uzupełniony deklaracją typu, co powoduje zadeklarowanie tak zwanego typu własnego cechy lub klasy. Definicja cechy PersonGreeting z pliku SelfType1.scala ilustruje taką sytuację.

Plik SelfType1.scala:
class Person(val name: String)
trait Greeting {
  def greet = "Hello"
}
trait PersonGreeting extends Greeting { person: Person =>
  override def greet = super.greet + " " + person.name
}

Cecha PersonGreeting rozszerza cechę Greeting i nadpisuje jej metodę greet. Nowa definicja metody odwołuje się, za pomocą przedrostka super, do nadpisanej metody. Jednocześnie definicja cechy wprowadza alias o nazwie person, deklarując jego typ jako Person. Taka definicja powoduje, że możliwe staje się w definicji metody greet odwołanie postaci person.name, w którym person jest aliasem instancji definiowanej cechy, a name jest wartością zdefiniowaną w klasie Person i dziedziczoną przez definiowaną cechę. W poniższym przykładzie tworzony jest obiekt z wykorzystaniem cechy PersonGreeting.

scala> (new Person("Peter") with PersonGreeting).greet
res0: String = Hello Peter

Próba utworzenia instancji z wykorzystaniem cechy PersonGreeting, ale bez udziału klasy Person nie jest prawidłowa i kończy się błędem kompilacji.

scala> new PersonGreeting {}
<console>:11: error: illegal inheritance;
 self-type PersonGreeting does not conform to PersonGreeting's selftype PersonGreeting with Person
       new PersonGreeting {}
           ^

Zmiana typu własnego nie wymaga jednoczesnego wprowadzania aliasu instancji. W pliku SelfType2.scala zdefiniowana jest cecha PersonGreeting2, w której zamiast aliasu użyty jest przedrostek this. Taka definicja jest prawidłowa.

Plik SelfType2.scala:
trait PersonGreeting2 extends Greeting { this: Person =>
  override def greet = super.greet + " " + this.name
}

W poniższym przykładzie tworzony jest obiekt dziedziczący z PersonGreeting2.

scala> (new Person("Paul") with PersonGreeting2).greet
res2: String = Hello Paul

Plik SelfType3.scala zawiera inny przykład. Zdefiniowana w nim cecha PersonGreeting3 ma typ własny, który rozszerza zarówno klasę Person, jak i cechę Exclamation. Definicja nadpisywanej metody greet może wywoływać metody odziedziczone z klasy Person oraz z cechy Exclamation.

Plik SelfType3.scala:
trait Exclamation {
  def exclamation = "!"
}
trait PersonGreeting3 extends Greeting { this: Person with Exclamation =>
  override def greet = super.greet + " " + this.name + this.exclamation
}

Poniższy przykład pokazuje sposób użycia wspomnianej cechy.

scala> (new Person("Mary") with PersonGreeting3 with Exclamation).greet
res3: String = Hello Mary!

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.