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!
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
}
