RestApi

Dáta sem, dáta tam.

Nástroje používateľa

Nástoje správy stránok


kotlin-zaklady

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 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. 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<Int> {
	for(i in m..n) {
		yield(i)    // yield() vracia hodnotu, zväčša do .forEach{} volajúcej fc
	}
}

Null safety

var myValue:<ValueType>? : 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<ValueType>()
val myArray: Array<ValueType>(val1, … val_n)
var myList: List<ValueType> = listOf() … myList += newValue … myList -= selectedList
Konverzie
val myArray: Array<CharSequence> = 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

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<MyEnum>
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:

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:
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

Iné vzdelávacie portály
Užitočné linky

Vzdelávacie linky

Tu sú uvedené linky na Kotlin portfolio vzdelávánie od JetBrains a Google.

Kotlin Docs - Základy (kotlinlang.org)
Kotlin Multiplatform - Začíname s KMP (kotlinlang.org)
Compose Multiplatform - Tvorba UI (jetbrains.com)
Ktor - Dokumentácia Ktor (ktor.io)
Android developers developers (developer.android.com)
kotlin-zaklady.txt · Posledná úprava: od attilajancik