|
1 | 1 | --- |
2 | 2 | layout: tour |
3 | 3 | title: Apstraktni tipovi |
| 4 | +language: ba |
4 | 5 |
|
5 | | -discourse: false |
| 6 | +discourse: true |
6 | 7 |
|
7 | 8 | partof: scala-tour |
8 | 9 |
|
9 | | -num: 22 |
10 | | - |
11 | | -language: ba |
12 | | - |
| 10 | +num: 23 |
13 | 11 | next-page: compound-types |
14 | 12 | previous-page: inner-classes |
15 | | ---- |
| 13 | +prerequisite-knowledge: variance, upper-type-bound |
16 | 14 |
|
17 | | -U Scali, klase su parameterizovane vrijednostima (parameteri konstruktora) i tipovima (ako su [generičke](generic-classes.html)). |
18 | | -Zbog dosljednosti, ne samo da je moguće imati vrijednosti kao članove objekta već i tipove. |
19 | | -Nadalje, obje forme članova mogu biti konkretne ili apstraktne. |
20 | | -Slijedi primjer koji sadrži obje forme: apstraktnu vrijednost i apstraktni tip kao članove [klase](traits.html) `Buffer`. |
| 15 | +redirect_from: "/tutorials/tour/abstract-types.html" |
| 16 | +--- |
21 | 17 |
|
22 | | - trait Buffer { |
23 | | - type T |
24 | | - val element: T |
25 | | - } |
| 18 | +Trejtovi i apstraktne klase mogu imati apstraktne tipove kao članove. |
| 19 | +To znači da konkretne implementacije definišu stvarni tip. |
| 20 | +Slijedi primjer: |
| 21 | + |
| 22 | +```tut |
| 23 | +trait Buffer { |
| 24 | + type T |
| 25 | + val element: T |
| 26 | +} |
| 27 | +``` |
| 28 | + |
| 29 | +U gornjem primjeru smo definisali apstraktni tip `T`. |
| 30 | +On se koristi za opis člana `element`. |
| 31 | +Ovaj trejt možemo naslijediti u apstraktnoj klasi i dodati gornju granicu tipa za `T` da bi ga učinili preciznijim. |
| 32 | + |
| 33 | +```tut |
| 34 | +abstract class SeqBuffer extends Buffer { |
| 35 | + type U |
| 36 | + type T <: Seq[U] |
| 37 | + def length = element.length |
| 38 | +} |
| 39 | +``` |
| 40 | + |
| 41 | +Primijetite da možemo koristiti još jedan apstraktni tip, `U`, kao gornju granicu tipa. Klasa `SeqBuffer` omogućuje čuvanje samo sekvenci u baferu kazivanjem da tip `T` |
| 42 | +mora biti podtip `Seq[U]` za neki novi apstraktni tip `U`. |
| 43 | + |
| 44 | +Trejtovi ili [klase](classes.html) s apstraktnim tip-članovima se često koriste u kombinaciji s instanciranjem anonimnih klasa. |
| 45 | +Radi ilustracije, pogledaćemo program koji radi s sekvencijalnim baferom koji sadrži listu integera: |
26 | 46 |
|
27 | | -*Apstraktni tipovi* su tipovi čiji identitet nije precizno definisan. |
28 | | -U gornjem primjeru, poznato je samo da svaki objekat klase `Buffer` ima tip-član `T`, |
29 | | -ali definicija klase `Buffer` ne kazuje kojem konkretno tipu odgovara `T`. |
30 | | -Kao i definicije vrijednosti, možemo redefinisati (override) definicije tipova u podklasama. |
31 | | -Ovo nam omogućuje da otkrijemo više informacija o apstraktnom tipu sužavanjem granica tipa (koje opisuju moguće konkretne instance apstraktnog tipa). |
| 47 | +```tut |
| 48 | +abstract class IntSeqBuffer extends SeqBuffer { |
| 49 | + type U = Int |
| 50 | +} |
32 | 51 |
|
33 | | -U sljedećem programu izvodimo klasu `SeqBuffer` koja omogućuje čuvanje samo sekvenci u baferu kazivanjem da tip `T` |
34 | | -mora biti podtip `Seq[U]` za neki novi apstraktni tip `U`: |
35 | 52 |
|
36 | | - abstract class SeqBuffer extends Buffer { |
37 | | - type U |
38 | | - type T <: Seq[U] |
39 | | - def length = element.length |
40 | | - } |
| 53 | +def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer = |
| 54 | + new IntSeqBuffer { |
| 55 | + type T = List[U] |
| 56 | + val element = List(elem1, elem2) |
| 57 | + } |
| 58 | +val buf = newIntSeqBuf(7, 8) |
| 59 | +println("length = " + buf.length) |
| 60 | +println("content = " + buf.element) |
| 61 | +``` |
41 | 62 |
|
42 | | -Trejtovi (trait) ili [klase](classes.html) s apstraktnim tip-članovima se često koriste u kombinaciji s instanciranjem anonimnih klasa. |
43 | | -Radi ilustracije, pogledaćemo program koji radi s sekvencijalnim baferom koji sadrži listu integera: |
| 63 | +Metoda `newIntSeqBuf` koristi anonimnu klasu kao implementaciju `IntSeqBuf` postavljanjem tipa `T` u `List[Int]`. |
44 | 64 |
|
45 | | - abstract class IntSeqBuffer extends SeqBuffer { |
46 | | - type U = Int |
47 | | - } |
48 | | - |
49 | | - object AbstractTypeTest1 extends App { |
50 | | - def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer = |
51 | | - new IntSeqBuffer { |
52 | | - type T = List[U] |
53 | | - val element = List(elem1, elem2) |
54 | | - } |
55 | | - val buf = newIntSeqBuf(7, 8) |
56 | | - println("length = " + buf.length) |
57 | | - println("content = " + buf.element) |
58 | | - } |
59 | | - |
60 | | -Povratni tip metode `newIntSeqBuf` odnosi se na specijalizaciju trejta `Buffer` u kom je tip `U` sada jednak `Int`u. |
61 | | -Imamo sličan alijas tip u anonimnoj instanci klase u tijelu metode `newIntSeqBuf`. |
62 | | -Ovdje kreiramo novu instancu `IntSeqBuffer` u kojoj se tip `T` odnosi na `List[Int]`. |
63 | | - |
64 | | -Imajte na umu da je često moguće pretvoriti apstraktni tip-član u tipski parametar klase i obrnuto. |
| 65 | +Često je moguće pretvoriti apstraktni tip-član u tipski parametar klase i obrnuto. |
65 | 66 | Slijedi verzija gornjeg koda koji koristi tipske parametre: |
66 | 67 |
|
67 | | - abstract class Buffer[+T] { |
68 | | - val element: T |
69 | | - } |
70 | | - abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T] { |
71 | | - def length = element.length |
72 | | - } |
73 | | - object AbstractTypeTest2 extends App { |
74 | | - def newIntSeqBuf(e1: Int, e2: Int): SeqBuffer[Int, Seq[Int]] = |
75 | | - new SeqBuffer[Int, List[Int]] { |
76 | | - val element = List(e1, e2) |
77 | | - } |
78 | | - val buf = newIntSeqBuf(7, 8) |
79 | | - println("length = " + buf.length) |
80 | | - println("content = " + buf.element) |
81 | | - } |
82 | | - |
83 | | -Primijetite da moramo koristiti [anotacije za varijansu](variances.html) ovdje; |
84 | | -inače ne bismo mogli sakriti konkretni tip sekvencijalne implementacije objekta vraćenog iz metode `newIntSeqBuf`. |
| 68 | +```tut |
| 69 | +abstract class Buffer[+T] { |
| 70 | + val element: T |
| 71 | +} |
| 72 | +abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T] { |
| 73 | + def length = element.length |
| 74 | +} |
| 75 | +
|
| 76 | +def newIntSeqBuf(e1: Int, e2: Int): SeqBuffer[Int, Seq[Int]] = |
| 77 | + new SeqBuffer[Int, List[Int]] { |
| 78 | + val element = List(e1, e2) |
| 79 | + } |
| 80 | +
|
| 81 | +val buf = newIntSeqBuf(7, 8) |
| 82 | +println("length = " + buf.length) |
| 83 | +println("content = " + buf.element) |
| 84 | +``` |
| 85 | + |
| 86 | +Primijetite da moramo koristiti [anotacije za varijansu](variances.html) ovdje (`+T <: Seq[U]`) da sakrijemo konkretni tip sekvencijalne implementacije objekta vraćenog iz metode `newIntSeqBuf`. |
85 | 87 | Nadalje, postoje slučajevi u kojima nije moguće zamijeniti apstraktne tipove tip parametrima. |
0 commit comments