1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
|
---
language: kotlin
contributors:
- ["S Webber", "https://github.com/s-webber"]
translators:
- ["Xavier Sala", "https://github.com/utrescu"]
lang: ca-es
filename: LearnKotlin-ca.kt
---
Kotlin és un llenguatge estàtic tipat per la JVM, Android i el navegador.
És interoperable al 100% amb Java.
[Llegir-ne més aquí.](https://kotlinlang.org/)
```kotlin
// Els comentaris d'una línia comencen amb //
/*
Els comentaris multilínia són com aquest
*/
// La paraula clau "package" funciona de la mateixa forma que en Java
package com.learnxinyminutes.kotlin
/*
El punt d'entrada dels programes en Kotlin és una funció anomenada "main".
La funció rep un array que té els arguments fets servir al executar-lo.
*/
fun main(args: Array<String>) {
/*
La declaració de variables es pot fer tant amb "var" com amb "val".
A les declarades amb "val" no se'ls hi pot canviar el valor
en canvi a les declarades amb "var" si.
*/
val fooVal = 10 // no es podrà canviar el valor de fooVal
var fooVar = 10
fooVar = 20 // fooVar si que es pot canviar
/*
Gairebé sempre, Kotlin pot determinar el tipus d'una variable,
de manera que no caldrà definir-lo cada vegada.
Però es pot definir el tipus d'una variable explícitament d'aquesta forma:
*/
val foo: Int = 7
/*
Els "strings" es poden representar igual que com es fa en Java.
Es poden escapar caràcters amb la barra inversa.
*/
val fooString = "Aquí està la meva cadena!"
val barString = "Imprimir en dues línies?\nCap problema!"
val bazString = "Es poden posar tabuladors?\tI tant!"
println(fooString)
println(barString)
println(bazString)
/*
Es poden definir strings literals envoltant-los amb les triples cometes
(""").
Dins hi poden haver tant salts de línies com d'altres caràcters.
*/
val fooRawString = """
fun helloWorld(val name : String) {
println("Hola món!")
}
"""
println(fooRawString)
/*
Els strings poden contenir expressions de plantilla.
Les expressions de plantilla comencen amb el símbol ($).
*/
val fooTemplateString = "$fooString té ${fooString.length} caràcters"
println(fooTemplateString)
/*
Perquè una variable pugui contenir null ha de ser declarada específicament
com a nullable afengint-li ? al seu tipus.
Es pot accedir a una variable nulable fent servir l'operador ?.
L'operador ?: permet especificar un valor alternatiu en cas de que la
variable sigui null.
*/
var fooNullable: String? = "abc"
println(fooNullable?.length) // => 3
println(fooNullable?.length ?: -1) // => 3
fooNullable = null
println(fooNullable?.length) // => null
println(fooNullable?.length ?: -1) // => -1
/*
Les funcions es declaren amb la paraula "fun".
Els arguments s'especifiquen entre corxets després del nom de la funció.
Els arguments poden tenir un valor per defecte.
El retorn de les funcions, si cal, es posa després de l'argument.
*/
fun hello(name: String = "món"): String {
return "Hola, $name!"
}
println(hello("foo")) // => Hola, foo!
println(hello(name = "bar")) // => Hola, bar!
println(hello()) // => Hola, món!
/*
Un dels paràmetres d'una funció pot ser marcat amb la paraula clau
"vararg" que permet que una funció accepti un número variable
d'arguments.
*/
fun varargExample(vararg names: Int) {
println("S'han rebut ${names.size} arguments")
}
varargExample() // => S'han rebut 0 elements
varargExample(1) // => S'ha rebut 1 element
varargExample(1, 2, 3) // => S'han rebut 3 elements
/*
Quan una funció consisteix en una sola expressió no calen els corxets
El cos de la funció es posa rere el símbol =.
*/
fun odd(x: Int): Boolean = x % 2 == 1
println(odd(6)) // => false
println(odd(7)) // => true
// Si el tipus retornat es pot determinar no cal especificar-lo.
fun even(x: Int) = x % 2 == 0
println(even(6)) // => true
println(even(7)) // => false
// Les funcions poden tenir altres funcions com arguments i
// fins i tot retornar-ne.
fun not(f: (Int) -> Boolean): (Int) -> Boolean {
return {n -> !f.invoke(n)}
}
// Les funcions amb nom es poden especificar quan fan d'arguments amb ::
val notOdd = not(::odd)
val notEven = not(::even)
// Les expressions lambda es poden posar com arguments.
val notZero = not {n -> n == 0}
/*
Si la lambda només té un paràmetre es pot ometre la seva declaració.
El seu valor serà "it".
*/
val notPositive = not {it > 0}
for (i in 0..4) {
println("${notOdd(i)} ${notEven(i)} ${notZero(i)} ${notPositive(i)}")
}
// Les classes es defineixen amb "class".
class ExampleClass(val x: Int) {
fun memberFunction(y: Int): Int {
return x + y
}
infix fun infixMemberFunction(y: Int): Int {
return x * y
}
}
/*
Per crear una nova instància es crida al constructor.
Tingueu en compte que Kotlin no té l'operador "new".
*/
val fooExampleClass = ExampleClass(7)
// Els mètodes es poden cridar amb la notació .
println(fooExampleClass.memberFunction(4)) // => 11
/*
Si una funció ha estat marcada amb "infix" es pot cridar amb la
notació infix.
*/
println(fooExampleClass infixMemberFunction 4) // => 28
/*
Les classes "data" són classes que només contenen dades.
Es creen automàticament els mètodes "hashCode","equals" i "toString"
*/
data class DataClassExample (val x: Int, val y: Int, val z: Int)
val fooData = DataClassExample(1, 2, 4)
println(fooData) // => DataClassExample(x=1, y=2, z=4)
// Les classes data tenen un mètode "copy".
val fooCopy = fooData.copy(y = 100)
println(fooCopy) // => DataClassExample(x=1, y=100, z=4)
// Els objectes es poden desestructurar amb múltiples variables
val (a, b, c) = fooCopy
println("$a $b $c") // => 1 100 4
// desestructurat en un bucle "for"
for ((a, b, c) in listOf(fooData)) {
println("$a $b $c") // => 1 100 4
}
val mapData = mapOf("a" to 1, "b" to 2)
// Els mapes també
for ((key, value) in mapData) {
println("$key -> $value")
}
// La funció "with" és similar a la de JavaScript.
data class MutableDataClassExample (var x: Int, var y: Int, var z: Int)
val fooMutableData = MutableDataClassExample(7, 4, 9)
with (fooMutableData) {
x -= 2
y += 2
z--
}
println(fooMutableData) // => MutableDataClassExample(x=5, y=6, z=8)
/*
Es pot crear una llista amb la funció "listOf".
La llista serà immutable - no s'hi poden afegir o treure elements.
*/
val fooList = listOf("a", "b", "c")
println(fooList.size) // => 3
println(fooList.first()) // => a
println(fooList.last()) // => c
// Es pot accedir als elements a partir del seu índex.
println(fooList[1]) // => b
// Es poden crear llistes mutables amb la funció "mutableListOf".
val fooMutableList = mutableListOf("a", "b", "c")
fooMutableList.add("d")
println(fooMutableList.last()) // => d
println(fooMutableList.size) // => 4
// Es poden crear conjunts amb la funció "setOf".
val fooSet = setOf("a", "b", "c")
println(fooSet.contains("a")) // => true
println(fooSet.contains("z")) // => false
// Es poden crear mapes amb la funció "mapOf".
val fooMap = mapOf("a" to 8, "b" to 7, "c" to 9)
// S'accedeix als valors del mapa a partir del seu índex.
println(fooMap["a"]) // => 8
/*
Les sequències representen col·leccions evaluades quan fan falta.
Podem crear una seqüencia amb la funció "generateSequence".
*/
val fooSequence = generateSequence(1, { it + 1 })
val x = fooSequence.take(10).toList()
println(x) // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// Per exemple amb aquesta seqüència es creen els números de Fibonacci:
fun fibonacciSequence(): Sequence<Long> {
var a = 0L
var b = 1L
fun next(): Long {
val result = a + b
a = b
b = result
return a
}
return generateSequence(::next)
}
val y = fibonacciSequence().take(10).toList()
println(y) // => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
// Kotlin proporciona funcions de primer ordre per treballar amb
// col·leccions.
val z = (1..9).map {it * 3}
.filter {it < 20}
.groupBy {it % 2 == 0}
.mapKeys {if (it.key) "parell" else "senar"}
println(z) // => {odd=[3, 9, 15], even=[6, 12, 18]}
// Es pot fer servir el bucle "for" amb qualsevol cosa que proporcioni
// un iterador.
for (c in "hello") {
println(c)
}
// els bucles "while" funcionen com en altres llenguatges.
var ctr = 0
while (ctr < 5) {
println(ctr)
ctr++
}
do {
println(ctr)
ctr++
} while (ctr < 10)
/*
"if" es pot fer servir com una expressió que retorna un valor.
Per això no cal l'operador ternari ?: en Kotlin.
*/
val num = 5
val message = if (num % 2 == 0) "parell" else "senar"
println("$num is $message") // => 5 is odd
// "when" es pot fer servir com alternativa a les cadenes "if-else if".
val i = 10
when {
i < 7 -> println("primer bloc")
fooString.startsWith("hola") -> println("segon bloc")
else -> println("bloc else")
}
// "when" es pot fer servir amb un argument.
when (i) {
0, 21 -> println("0 o 21")
in 1..20 -> println("en el rang 1 a 20")
else -> println("cap dels anteriors")
}
// "when" es pot fer servir com una funció que retorna valors.
var result = when (i) {
0, 21 -> "0 o 21"
in 1..20 -> "en el rang 1 a 20"
else -> "cap dels anteriors"
}
println(result)
/*
Es pot comprovar el tipus d'un objecte fent servir l'operador "is".
Si un objecte passa una comprovació es pot fer servir sense posar-hi
cap casting.
*/
fun smartCastExample(x: Any) : Boolean {
if (x is Boolean) {
// x es converteix automàticament a Booleà
return x
} else if (x is Int) {
// x es converteix automàticament a int
return x > 0
} else if (x is String) {
// x es converteix a string automàticament
return x.isNotEmpty()
} else {
return false
}
}
println(smartCastExample("Hola món!")) // => true
println(smartCastExample("")) // => false
println(smartCastExample(5)) // => true
println(smartCastExample(0)) // => false
println(smartCastExample(true)) // => true
// També es pot cridar smarcast en un bloc when
fun smartCastWhenExample(x: Any) = when (x) {
is Boolean -> x
is Int -> x > 0
is String -> x.isNotEmpty()
else -> false
}
/*
Les extensions són una forma d'afegir noves funcionalitats a una classe.
És semblant a les extensions de C#.
*/
fun String.remove(c: Char): String {
return this.filter {it != c}
}
println("Hola món!".remove('l')) // => Hoa, món!
println(EnumExample.A) // => A
println(ObjectExample.hello()) // => hola
}
// Les classes enumerades són semblants a les de Java
enum class EnumExample {
A, B, C
}
/*
El paràmetre "object" es pot fer servir per crear objectes singleton.
No es poden instanciar però es pot fer referència a la seva única instància
amb el seu nom.
Són similars als singletons d'Scala.
*/
object ObjectExample {
fun hello(): String {
return "hola"
}
}
fun useObject() {
ObjectExample.hello()
val someRef: Any = ObjectExample // podem fer servir el nom de l'objecte
}
```
### Per llegir més
* [tutorials de Kotlin](https://kotlinlang.org/docs/tutorials/)
* [Provar Kotlin en el navegador](http://try.kotlinlang.org/)
* [Llista de recursos de Kotlin](http://kotlin.link/)
|