Skip to content

Commit a00217a

Browse files
authored
Merge pull request scala#1221 from kamilduda/pl/tour/mixin
Polish translation of Tour of Scala: Mixins
2 parents d8bcd81 + b3e0c46 commit a00217a

File tree

1 file changed

+53
-21
lines changed

1 file changed

+53
-21
lines changed

_pl/tour/mixin-class-composition.md

+53-21
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,43 @@
11
---
22
layout: tour
3-
title: Kompozycja domieszek
3+
title: Kompozycja klas przez domieszki
44

55
discourse: false
66

77
partof: scala-tour
88

9-
num: 6
9+
num: 7
1010
language: pl
1111
next-page: higher-order-functions
1212
previous-page: tuples
1313
---
1414

15-
W przeciwieństwie do języków, które wspierają jedynie pojedyncze dziedziczenie, Scala posiada bardziej uogólniony mechanizm ponownego wykorzystania klas. Scala umożliwia wykorzystanie _nowych elementów klasy_ (różnicy w stosunku do klasy bazowej) w definicji nowej klasy. Wyraża się to przy pomocy _kompozycji domieszek_.
15+
Domieszka (ang. mixin) to cecha (trait), która używana jest do komponowania klas.
1616

17-
Rozważmy poniższe uogólnienie dla iteratorów:
17+
{% scalafiddle %}
18+
```tut
19+
abstract class A {
20+
val message: String
21+
}
22+
class B extends A {
23+
val message = "Jestem instancją klasy B"
24+
}
25+
trait C extends A {
26+
def loudMessage = message.toUpperCase()
27+
}
28+
class D extends B with C
29+
30+
val d = new D
31+
println(d.message) // wyświetli "Jestem instancją klasy B"
32+
println(d.loudMessage) // wyświetli "JESTEM INSTANCJĄ KLASY B"
33+
```
34+
{% endscalafiddle %}
35+
36+
Klasa `D` posiada nadklasę `B` oraz domieszkę `C`.
37+
Klasy mogą mieć tylko jedną nadklasę, ale wiele domieszek (używając kolejno słów kluczowych `extends`, a następnie `with`).
38+
Domieszki i nadklasy mogą posiadać tą samą nadklasę (typ bazowy).
39+
40+
Spójrzmy teraz na trochę ciekawszy przykład zawierający klasę abstrakcyjną.
1841

1942
```tut
2043
abstract class AbsIterator {
@@ -24,35 +47,44 @@ abstract class AbsIterator {
2447
}
2548
```
2649

27-
Następnie rozważmy klasę domieszkową, która doda do klasy `AbsIterator` metodę `foreach` wykonującą podaną funkcję dla każdego elementu zwracanego przez iterator. Aby zdefiniować klasę domieszkową, użyjemy słowa kluczowego `trait`:
50+
Klasa ta zawiera abstrakcyjny typ `type T` oraz standardowe metody iteracyjne `hasNext` i `next`.
2851

2952
```tut
30-
trait RichIterator extends AbsIterator {
31-
def foreach(f: T => Unit) { while (hasNext) f(next()) }
53+
class StringIterator(s: String) extends AbsIterator {
54+
type T = Char
55+
private var i = 0
56+
def hasNext = i < s.length
57+
def next() = {
58+
val ch = s charAt i
59+
i += 1
60+
ch
61+
}
3262
}
3363
```
3464

35-
Oto przykład konkretnego iteratora, który zwraca kolejne znaki w podanym łańcuchu znaków:
65+
Klasa `StringIterator` przyjmuje parametr typu `String`, może być ona użyta do iterowania po typach String (np. aby sprawdzić czy String zawiera daną literę).
66+
67+
Stwórzmy teraz cechę, która również rozszerza `AbsIterator`.
3668

3769
```tut
38-
class StringIterator(s: String) extends AbsIterator {
39-
type T = Char
40-
private var i = 0
41-
def hasNext = i < s.length()
42-
def next() = { val ch = s charAt i; i += 1; ch }
70+
trait RichIterator extends AbsIterator {
71+
def foreach(f: T => Unit): Unit = while (hasNext) f(next())
4372
}
4473
```
4574

46-
Chcielibyśmy także połączyć funkcjonalność `StringIterator` oraz `RichIterator` w jednej klasie. Z pojedynczym dziedziczeniem czy też samymi interfejsami jest to niemożliwe, gdyż obie klasy zawierają implementacje metod. Scala pozwala na rozwiązanie tego problemu z użyciem _kompozycji domieszek_. Umożliwia ona ponowne wykorzystanie różnicy definicji klas, tzn. wszystkich definicji, które nie zostały odziedziczone. Ten mechanizm pozwala nam na połączenie `StringIterator` z `RichIterator`, tak jak w poniższym przykładzie - gdzie chcielibyśmy wypisać w kolumnie wszystkie znaki z danego łańcucha:
75+
Cecha `RichIterator` implementuje metodę `foreach`, która z kolei wywołuje przekazaną przez parametr funkcję `f: T => Unit` na kolejnym elemencie (`f(next())`) tak długo, jak dostępne są kolejne elementy (`while (hasNext)`).
76+
Ponieważ `RichIterator` jest cechą, nie musi implementować abstrakcyjnych składników klasy `AbsIterator`.
77+
78+
Spróbujmy teraz połączyć funkcjonalności `StringIterator` oraz `RichIterator` w jednej klasie.
4779

4880
```tut
49-
object StringIteratorTest {
50-
def main(args: Array[String]) {
51-
class Iter extends StringIterator("Scala") with RichIterator
52-
val iter = new Iter
53-
iter foreach println
54-
}
81+
object StringIteratorTest extends App {
82+
class RichStringIter extends StringIterator("Scala") with RichIterator
83+
val richStringIter = new RichStringIter
84+
richStringIter foreach println
5585
}
5686
```
5787

58-
Klasa `iter` w funkcji `main` jest skonstruowana wykorzystując kompozycję domieszek `StringIterator` oraz `RichIterator` z użyciem słowa kluczowego `with`. Pierwszy rodzic jest nazywany _klasą bazową_ `Iter`, podczas gdy drugi (i każdy kolejny) rodzic jest nazywany _domieszką_.
88+
Nowo powstała `RichStringIter` posiada `StringIterator` jako nadklasę oraz `RichIterator` jako domieszkę.
89+
90+
Mając do dyspozycji jedynie pojedyncze dziedziczenie, nie byli byśmy w stanie osiągnąć takiego stopnia elastyczności.

0 commit comments

Comments
 (0)