====== Kotlin - základy ======
===== Úvod =====
Kotlin je moderný programovací jazyk. Vytvorila ho firma JetBrains. Vysokú podporu má od Google a preto je využitý v platforme Android. Je však natoľko univerzálny a má takú podporu knižníc, že je využitý i pre multiplatformové nasadenie pre iOS, web frontend (JavaScript), Linux, Windows a aj servery (Ktor), kde beží pod JVM (Java, napríklad [[https://tomcat.apache.org/|Apache Tomcat]]).
Vyznačuje sa stručnosťou (oproti Java). Je možné v jednom projekte kombinovať Java aj Kotlin. Bezpečnosť voči **null** ukazateľom je vyriešená (null safety). **Lambda** funkcie výrzane uľahčujú písanie a stručnosť kódu. [[kotlin-coroutines|Coroutins]] zjednodušujú prácu s asynchronnými procesmi (vlákna) a preberanie odpovedí z nich.
===== Základné špecifikácie a príkazy =====
==== Označenie premenných ====
var : variable (dynamický obsah)\\
val : value (konštantná hodnota)
==== Typy premenných ====
=== Celé čísla ===
| Byte | -128..127, 8 bit |
| Short | -32768..32767, 16 bit |
| Int | -2147483648..2147483647, 32 bit |
| Long | -263 .. 263 - 1, 64 bit |
=== Desatinné čísla ===
| Float | %%+-1.4 * 10^−45 .. +-3.4 * 1038, presnosť: 7 čísel%% |
| Double | %%+-5.0 * 10^−324 .. +-1.7 * 10308, presnosť: 15 .. 16 čísel%% |
=== Ďalšie typy ===
| Char | 16 bit |
| Boolean | 8 bit |
| String |
==== Operátory ====
==, >, <, %%<=%%, %%>=%%, !=, !
==== Podmienky ====
if () \\
if() else \\
if() else if() \\
when(var) {…} %%\\%% when(val) {val -> {…} else -> {…}} \\
when() else \\
=== reťazenie podmienok ===
&&, ||
==== Cykly ====
for (i in m..n) \\
while () \\
repeat(n) {}
it : aktuálny riadok cyklu
fun myFc() = sequence {
for(i in m..n) {
yield(i) // yield() vracia hodnotu, zväčša do .forEach{} volajúcej fc
}
}
==== Null safety ====
var myValue:? : povolenie null \\
anyCommand(myValue!!) : vypnutie kontroly \\
myValue?.let { anyCommand } : bezpečné volanie \\
anyCommand(myValue?.anyMethod ?: defaultValue) : bezpečné volanie s elvis operátorom \\
==== Polia ====
var myArray = arrayOf() \\
val myArray: Array(val1, … val_n) \\
var myList: List = listOf() … myList += newValue … myList -= selectedList \\
**Konverzie** \\
val myArray: Array = myArrayList.toTypedArray() %%//%% ArrayLit to Array
==== Reťazce ====
**časté funkcie:**
* contains(), endsWith(), startsWith()
* toUpperCase(), toLowerCase()
* replace()
* trim()
* first(), last(), indexOf()
* substring(), compareTo()
* split(), joinToString()
* length
**Matematické funkcie** \\
import kotlin.math.*
* konštanty: PI, E
* min(), max()
* round(), ceil(), floor(), truncate()
* abs(), sign()
* sin(), cos(), tan(), acos(), asin(), atan()
* pow(), sqrt() : myDouble.pow(n)
* exp(), log(), log10(), log2()
* /, %
====== Objektové programovanie - OOP ======
=== class - Trieda: ===
* **zapúzdrenie** : skrytie atribútov a metód
* **dedičnosť** : od pôvodných tried
* **polymorfizmus** : prepísanie metód
==== Deklarácie ====
=== Deklarácia triedy ===
class MyClass { … }
=== Deklarácia metódy ===
[modifikatorPristupu] [menoMetody] ([parametre]) : [navratovyTyp]
* fun
=== Deklarácia vlastnosti ===
* var, val : základné
=== Vytvorenie inštancie ===
* automatocké vytvorenie koštruktora pri vytvorení inštancie
val myValue = MyClass()
=== Konštruktory ===
class MyClass(myValue: ValueType) {
val myVal: ValueType
init {
this.myVal = myValue
}
}
class MyClass(val myValue: ValueType) {
constructor() : this(defaultValue)
}
==== Zapúzdrenie ====
* private val/var/fun : bez dedičnosti
* protected val/var/fun : v materskej triede
* open fun : v materskej triede
* call getter and setter from java: getPropertyName(), setPropertyName() - auto generate g/s in Kotlin
class MyClass(private var myValue) { // getters and setters
fun getMyValue(): ValueType { // getter
return myValue
}
fun setMyValue(myVal valueType) { // setter
myValue = myVal
}
}
class MyClass(myValue: ValueType) { // private set
var myValue = myValue
private set
}
class MyClass(myValue: ValueType) { // backing properties
var myValue = myValue
private set
get() {
return expressionResult
}
}
class MyClass(myValue: ValueType) { // set value
var myValue = myValue
[private] set(value) {
foo = value
}
}
==== Dedičnosť ====
* open class MyOriginalClass { … }
* class MyNewClass: MyOriginalClass { … }
open calss MyParentClass(protected val myOirginalVale: ValueType) {
…
}
class MyChildClass(myOirginalVale: ValueType, private var myOtherValue: ValueType) : MyParentClass(myOirginalVale) {
…
init {
this.myOtherValue = myOtherValue
}
}
==== Polymorfizmus ====
stejné meno metódy v dcérskej triede ako v materskej, ale iná funkcia
* override fun parentMethod() { … }
==== Companion objects - statika ====
class MyClass() {
…
companion object {
val myValue = anyValue
private var myLocalValue = anyValue
fun myMethod(…): returnValueType { … }
}
}
==== Privátny konštruktor ====
statická trieda - objekt, bude dostupné všade aj bez inštancie
object MyObject {
init { … }
val/var/fun …
}
==== Rozhranie ====
* samostaná deklarácia verejných metód
* nový interface sa genereje v IDE : New -> Kotlin File/Class -> Interface
* ak sú v rozhraní vytvorené aj telá metód, potom sa jedná o trait
* vicnásobná dedičnosť
== rozhranie: ==
interface MyInterface {
fun anyFunction()
}
== základná trieda: ==
class MyClass: MyInterface {
override fun anyFunction() {
…
}
}
== volanie: ==
val myClass: MyInterface = MyClass()
=== viacnásobná dedičnosť ===
== ďalšie rozhranie: ==
interface NextInterface {
fun nextFunction()
}
== ďalšia trieda: ==
klik na žiarovku -> Implement members
class NextClass: MyInterface, NextInterface {
override fun anyFunction() {
…
}
override fun nextFunction() {
…
}
}
== volanie: ==
val nextClass = NextClass()
== volanie1: ==
val myClass: MyInterface = NextClass()
=== pretypovanie ===
* je možné na triedu i na rozhranie
val myClass: MyInterface = NextClass()
== ok volanie: ==
myClass.anyFunction()
== chybné volanie: ==
myClass.nextFunction()
== ok volanie - pretypované: ==
(myClass as NextClass).nextFunction()
== iné: ==
- if (myClass is MyClass) { … }
- (myClass as MyClass).anyFunction()
==== Abstraktná trieda ====
* https://www.itnetwork.cz/kotlin/oop/abstraktni-trida-porovnavani-a-operatory-v-kotlin
* netvoria sa z nej inštancie (potomkovia)
* deklarujú sa hlavičky metód, nie telá, tie sa prepisujú u potomkov - akoby zlúčenie triedy a rozhrania
* abstract fun myMethod() -> overrie fun myMethod() { … }
* abstract class MyClass(var anyValue: ValueType) { … }
==== Porovnanie objektov ====
* dajú sa porovnávať iba prvky, ktoré implementujú rozhranie Comparable, obsahujúce abstraktnú metódu compareTo(), kde návratová hodnota je -1, 0, 1
* override fun copareTo(other: MyClass): Int { return -1 or 0 or 1 }
* je možné vytvoriť triedu implementujúcu rozhranie Comparator pre predanie jej inštancií metóde sortWith()
* porovnanie je ďalej možné aj anonymnou funkciou a pomocou metódy sortBy()
==== Preťažovanie operátorov ====
* operator fun plus(myClass: MyClass): MyClass? { … }
==== Enum - výčtový typ ====
* prednastavené hodnoty
* nový enum sa genereje v IDE : New -> Kotlin File/Class -> Enum class
* enum class MyEnum { … }
* if (myStatus == MyEnum.myDefinitionValue) { … }
== rozširenie enum o metódy: ==
enum class MyEnum {
MyStatus1 {
override fun toString(): String {
return “anyString1”
}
},
MyStatus2 {
override fun toString(): String {
return “anyString2”
}
}
}
== prípadne: ==
enum class MyEnum(private val text: String) { // ! (private val text: String) je konštruktor ktorý vytvára v triede inštanciu
MyStatus1(“anyString1”),
MyStatus2(“anyString2”);
override fun toString(): String {
return text
}
}
=== Set - množina ===
* enum môže nadobúdať viacero stavov (napríklad práva používateľov)
private var myEnum: Set
init {
myEnum(MyEnum.MyStatus1, MyEnum.MyStatus2)
}
myEnum += MyEnum.MyStatusN
myEnum -= MyEnum.MyStatusN
if (myEnum.contains(MyStatus1)) { … }
==== Konštanty ====
* súčasť triedy Any (všetky triedy sú jej potomkom…)
* sú konštantné vo svojej viditeľnosti kódu (príklad: kotlin.math -> PI, E)
* zmena hodnoty je možná len v mieste jej definície
* definícia: const val MY_CONST_VALUE = anyValue
class MyClass {
companion object { // static, use: myClass.MY_CONST_VALUE
const val MY_CONST_VALUE = anyValue
// const val je nastavená pri kompilácii, val môže meniť hodnotu napríklad z konštruktoru
}
}
==== Equals ====
* v základe porováva len referencie na inštancie
* generovanie equals() a hashCode(): rightClick na názov triedy -> Generate -> "equals() and hashCode()”, následne je použitľné porovnanie:
if (myClass_instance1 == myClass_instance2) { … }
==== Klonovanie ====
* objekt dedí z Any aj protected clone()
== plytká kópia - shallow copy: ==
* atribúty sú nezávislé
* inštancie odkazujú v klone na pôvodné objekty
== rozhranie Clonable: ==
class MyClass(val myVal: typeVal) Clonable { … } // Clonable je marker-interface
- clone() je protected a definuje sa v triede:
class MyClass(val myVal: typeVal) Clonable {
public override fun clone(): Any {
return super.clone()
}
}
== hlboká kópia - deep copy: ==
* klonujú sa všetky vnútorné inštancie
public fun clone(): Any {
val obj1 = super.clone() as Obj1
obj1.instX = obj1.instX.clone() as Obj2
return obj1
}
==== Datová trieda ====
* eliminuje zdĺhavosť tvorby equals(), hashCode(), toString(), componentN(), copy(), clone() a iné - generuje ich automaticky
* sú vhodné pre modely (dátové - uchovanie dát)
* primány konštruktor musí obsahovať minimálne jeden parameter (val alebo var)
data class Obj1(val val1: String, …)
* sekundárny konštruktor je v tele
data class Obj1(val val1: String, …) {
constructor(val val1: String) : this(val val1: String, “other string parameter”, …)
}
==Linky:==
* https://kotlinlang.org/docs/data-classes.html#data-classes-and-destructuring-declarations
* https://www.baeldung.com/kotlin/data-classes
==== Balíčky - packages ====
* určujú umiestnenie objektov v rámci projektu
* napríklad: LocalDate.now() == java.time.LocalDate.now()
==== Metóda s premenným počtom parametrov ====
* pomocou vararg príjma metóda premenlivý počet parametrov rovnakého typu
* prijaté parametre sú uložené v poli
* poľu môžu predchádzať iné parametre
fun fun1(…, Ivararg vars1: ValType): ValType {
for (item in vars1) {
…
}
return result
}
==== Preťažovanie a prekrývanie metód ====
=== Preťažovanie metód ===
* stejný názov, ale iné parametre
* pri preťažení konštruktorov za zátvorku konštruktora vložíme: : this( …iné parametre… )
* volanie konštruktora predka: : super(parametre)
=== Prekrývanie metód ===
* ak je v rodičovi metóda označená open, potom v potomkovi ju prepíšeme označením override
* metóda predka sa v potomkovi volá: super.metoda()
==== Vnorené triedy ====
class Obj1 {
class Obj2 {
}
}
* - prístup: Obj1.Obj2
==== Východzie parametre ====
* nastaví sa, ak nie je uvedený (podobne ako v PHP)
fun fun1(par1: ValType, par2: ValType = anyValue) { ... }
==== Parametre s menom ====
* volať funkciu je možn aj s menom parametru, čo je vhodné ak sa zmení poradie v definícii
funX(par2 = anyValue, par1 = anyValue)
==== Jednovýrazové funkcie ====
fun fun1(): ValType = anyValue + anyValue // príklad pre sčítanie
----
====== Pomôcky ======
===== Dátum a Čas =====
Odporúča sa použiť LcalDateTime z Java 8, nie Date, alebo Calendar, alebo Joda-Time
== získanie: ==
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.Month
== aplikovanie: ==
val datumCas = LocalDateTime.of(2016, Month.APRIL, 15, 3, 15) // dátum a čas
val datum = LocalDate.of(2016, Month.APRIL, 15) // len dátum
val cas = LocalTime.of(3, 15, 10) // len čas
val datumCas = LocalDateTime.now()
val datum = LocalDate.now()
val cas = LocalTime.now()
== formátovanie: ==
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
== aplikovanie: ==
val dateTime = LocalDateTime.now()
println(dateTime.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM)))
println(dateTime.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)))
println(dateTime.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG, FormatStyle.SHORT)))
println(dateTime.format(DateTimeFormatter.ofPattern("d.M.y H:m:ss")))
== prevody z LocalDateTime: ==
https://www.itnetwork.cz/kotlin/oop/datum-a-cas-v-kotlin-uprava-a-intervaly
toLocalDate()
toLocalTime()
== prevody na LocalDateTime: ==
val zacatek = LocalDate.of(1939, 9, 1)
val datumCas = zacatek.atStartOfDay()
val datumCas2 = zacatek.atTime(0, 0)
== úpravy hodnôt: ==
minusDays(), minusHours(), minusMinutes(), minusMonths(), minusNanos(), minusSeconds(), minusWeeks(), minusYears()
plusDays(), plusHours(), plusMinutes(), plusMonths(), plusNanos(), plusSeconds(), plusWeeks(), plusYears()
== Period a Duration: ==
import java.time.Period
práca s intervalom - minus(), plus() => Period a Duration
Duraton je len interval bez súvisu na kalendár
Pariod akceptuje prechody na letný/zimný čas
== ChronoUnit: ==
import java.time.temporal.ChronoUnit
pre prácu s intervalom (pre Duration)
== Betwen: ==
získanie intervalu medzi dvoma dátumami
== porovnanie: ==
compareTo(), isAfter(), isBefore(), isEqual(), isLeapYear(), isSupported(ChronoUnit.X)
== ostatné: ==
Instant : nanosekundy od 1.1.1970 - Instant.now() #thisDteIsBeginOfLinuxEpoch
ZoneId : špecifikácia zóny - ZonedDateTime.now(ZoneId.of("America/New_York"))
.ofEpochSecond() : linux timestamp = sekundy od 1.1.1970 : LocalDate.ofEpochSecond()
toEpochSecond(), toEpochDay() : prevod na sekundy
===== Systém =====
== Melanie času behu ==
po ukončení bloku ''measureTimeMillis {}'' je vrátený čas jeho trvania v milisekundách:
val runningTime = measureTimeMillis {
dataOperation()
}
println(runningTime)
====== Linky ======
* kotlin playground: https://play.kotlinlang.org/
* java playground: https://dev.java/playground/
* kotlinlang.org : [[https://kotlinlang.org/| kurz Kotlin]], JetBrains
* developer.android : [[https://developer.android.com/kotlin|všetko o Kotline]]
* w3schools : [[https://www.w3schools.com/kotlin/index.php|Kotlin tutorial]]
* https://www.itnetwork.cz/kotlin všetky kurzy
* https://www.itnetwork.cz/kotlin/zaklady základy
* https://www.itnetwork.cz/kotlin/oop OOP
* https://kotlinlang.org/docs/coding-conventions.html#lambdas Lambda výrazy
== Iné vzdelávacie portály ==
* https://www.baeldung.com/kotlin/intro
== Užitočné linky ==
* Ktor - framework pre : server, client, multiplatform : https://ktor.io/docs/welcome.htm
* info o Ktor pre Android: https://medium.com/@stefanoq21/ktor-my-favorite-http-client-for-android-3955c2c2cd7c
* Kotlin Multiplatform - get started: https://www.jetbrains.com/help/kotlin-multiplatform-dev/get-started.html
====== Vzdelávacie linky ======
Tu sú uvedené linky na Kotlin portfolio vzdelávánie od JetBrains a Google.
> Kotlin Docs - [[https://kotlinlang.org/docs/home.html|Základy]] (kotlinlang.org)
> Kotlin Multiplatform - [[https://kotlinlang.org/docs/multiplatform/get-started.html|Začíname s KMP]] (kotlinlang.org)
> Compose Multiplatform - [[https://www.jetbrains.com/compose-multiplatform/|Tvorba UI]] (jetbrains.com)
> Ktor - [[https://ktor.io/docs/welcome.html|Dokumentácia Ktor]] (ktor.io)
> Android developers [[https://developer.android.com/|developers]] (developer.android.com)