9.1. Typy zawierające parametry

Definicje klas i cech w języku Scala mogą zawierać parametry typu. Parametry te umieszcza się w postaci listy identyfikatorów oddzielonych przecinkami, zawartej w nawiasach kwadratowych i umieszczonej po nazwie klasy lub cechy. Tak zdefiniowane parametry można następnie używać w ciele klasy/cechy. Klasy lub cechy zawierające parametry typu będziemy nazywać typami ogólnymi. Definicja klasy Box, z pliku TypeParameters1.scala, zawiera parametr typu, nazwany T.

Plik TypeParameters1.scala:
class Box[T](val content: T) {
  override def toString = "[" + content + "]"
}

Parametr T jest zadeklarowany w nawiasach kwadratowych umieszczonych po nazwie klasy. Następnie jest użyty w deklaracji parametru content. Instancję klasy Box możemy utworzyć następująco.

scala> val a = new Box[Int](5)
a: Box[Int] = [5]

Wyrażenie tworzące instancję klasy zawiera, po nazwie klasy, nawiasy kwadratowe z umieszczoną wewnątrz nazwą typu. W tym przypadku jest to typ Int. Utworzony obiekt jest typu Box[Int], a typem wartości content jest Int.

scala> a.content
res0: Int = 5

Typ argumentu konstruktora użytego w wyrażeniu tworzącym instancję klasy Box nie może być w konflikcie z typem zadeklarowanym w nawiasach kwadratowych. Poniższe wyrażenie jest błędne, gdyż argument typu Symbol nie odpowiada wymaganemu typowi Int.

scala> val b = new Box[Int]('abc)
<console>:10: error: type mismatch;
 found   : Symbol
 required: Int
       val b = new Box[Int]('abc)
                            ^

Jeśli nawiasy klamrowe i specyfikacja typu zostaną pominięte w wyrażeniu tworzącym nową instancję typu ogólnego, to kompilator może podjąć próbę wywnioskowania jakie typy mają zostać użyte w miejscu parametrów typu.

scala> val c = new Box('abc)
c: Box[Symbol] = ['abc]

W powyższym przykładzie nawiasy kwadratowe wraz z zawartością zostały pominięte w wyrażeniu tworzącym nowy obiekt. Mimo to Scala poradziła sobie z utworzeniem obiektu. Typ parametru T został wywnioskowany i ustalony na Symbol na podstawie wartości argumentu konstruktora.

Plik TypeParameters2.scala zawiera definicję klasy mającej dwa parametry typu.

Plik TypeParameters2.scala:
class PairBox[A,B](val a: A, val b: B) {
  override def toString = "[" + a + "," + b + "]"
}

Poniżej przedstawione są przykładowe wyrażenia tworzące instancje tej klasy.

scala> val d = new PairBox[Int,Double](4,6.7)
d: PairBox[Int,Double] = [4,6.7]

scala> val e = new PairBox('a,4.5f)
e: PairBox[Symbol,Float] = ['a,4.5]

scala> val f = new PairBox(1,2)
f: PairBox[Int,Int] = [1,2]

Ostatni z przykładów ilustruje to, że nie jest błędem użycie tego samego typu w przypadku dwóch różnych parametrów typu. W tym przykładzie oba parametry — zarówno A, jak i B — przyjmują wartość Int.

Jeśli parametry typu zostają umieszczone w sposób jawny w wyrażeniu tworzącym instancję, to muszą być podane wszystkie. Natomiast jeśli zostają pominięte, to również muszą być pominięte wszystkie. Błędem jest próba jawnej deklaracji tylko części parametrów, jak w poniższym przykładzie.

scala> val g = new PairBox[Int](1,"ac")
<console>:10: error: wrong number of type arguments for PairBox, should be 2
       val g = new PairBox[Int](1,"ac")
                   ^

Typ zawierający dwa parametry może być zapisany jako tak zwany typ infiksowy. Deklaracja typu infiksowego ma postać T x S, co jest odpowiednikiem zapisu x[T,S]. Poniższy przykład ilustruje użycie klasy PairBox w deklaracji typu infiksowego.

scala> val h: Int PairBox Long = new PairBox(5, 7L)
h: PairBox[Int,Long] = [5,7]

Specyfikacja języka Scala opisuje typy zawierające parametry w punkcie 3.2.4, typy infiksowe w punkcie 3.2.8, a parametry typu w punkcie 4.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.