====== 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)