Kotlin

As explaines by freeCodeCamp.org and https://kotlinlang.org/docs/

Variables and Constants

val width: Int = 100          //constant
val width = 100               //constant

var name = "Test"             //variable
var greeting: String? = null  //nillable

Control structures

var greeting: String? = null  //nillable

if (greeting != null){
  print(greeting)
} else{
  print("Hi")
}
var greeting: String? = null  //nillable

when(greeting){
  null -> print("Hi")
  else -> print(greeting)
}
val gretingToPrint = if(greeting != null) greeting else "Hi"
print(gretingToPrint)
val gretingToPrint = when(greeting){
  null -> "Hi"
  else -> greeting
}
print(gretingToPrint)

Functions

fun getGreeting(name: String?): String {
 return "Hello Kotlin"
}

fun sayHello(): Unit { // basically void
  printl(getGreeting)
}

fun sayHello() { // still void
  printl(getGreeting)
}
fun getGreeting(name: String?): String? {
 retrun null
}
fun getGreeting(): = "Hello World" // single expression function
fun sayHello(name: String?):{
  val msg = "Hello "+name
  print(msg)
}
fun sayHello(name: String?):{ 
  print("Hello $name") // a string template
}
fun sayHello(greeting: String, name: String?) = print("$greeting $name")
  • ☝️ Toplevel functions/free functions exist outside of classes.

fun sayHello(greeting: String, names: List<String>)}{
  names.forEach{ item ->
    print("$greeting $item")
  }
}

names = listOf("A", "B")
sayHello("Hi", names) //parameter names must be set
  • vararg

fun sayHello(greeting: String, vararg names: String}{
  names.forEach{ item ->
    print("$greeting $item")
  }
}

names = listOf("A", "B")
sayHello("Hi")                //works
sayHello("Hi", "A", "B", "C") //works
  • spread operator

names = arrayOf("A", "B")
sayHello("Hi", *names)        //spread operator
  • named arguments

func greetPerson(greeting: String, name: String) = println("$greeting $name")

greetPerson("Hi", "Hans")
greetPerson(greeting = "Hi", name = "Hans")
  • default parameters

fun sayHello(greeting: String = "Hello", vararg names: String = "Kotlin"}{
  names.forEach{ item ->
    print("$greeting $item")
  }
}

sayHello(name = "Hans")
sayHello()

sayHello(greeting: “Hi”, ar )

Types

https://kotlinlang.org/docs/

  • Byte

  • Short

  • Int

  • Long

  • Float

  • Double

  • UByte

  • UShort

  • UInt

  • ULong

  • Boolean

  • Char

  • String

  • Array

Complex Types

  • Collections and Iteration

  • Array

  • List

  • Map

val ar = arrayOf("Val1", "Val2")
print(ar.size)
print(ar[0])
print(ar.get(0))

for (a in ar) {
 print(a)
}

ar.forEach {
  print(it) //it is the default name
}

ar.forEach { variableName ->
  print(variableName)s
}

ar.forEachIndexed { idx,variableName ->
  print(" $idx $variableName")
}
val ar = listOf("Val1", "Val2")
print(ar.size)
print(ar[0])
print(ar.get(0))

ar.forEach {
  print(it) //it is the default name
}
val map = mapOf( 1 to "a", 2 to "b", 3 to "c")

map.forEach{ key,value ->
  print("$key -> $value")
}
  • ☝️ Mutable and inmutable collection types.

val ar = listOf("Val1", "Val2") //not mutable by default
val ar = mutuableListOf("Val1", "Val2")
ar.add("Bla")
val map = mutableMapOf( 1 to "a", 2 to "b", 3 to "c")
ar.put(4 to "d")
val ar = listOf("Val1", "Val2") //not mutable by 

fun sayHello(greeting:String, names:List<String>)}{
  names.forEach{ item ->
    print("$greeting $item")
  }
}

sayHello("Hi", ar )

Classes

class Person {
}

equals

class Person 

equals

class Person constructor()

equals

class Person()
val person = Person() //default constructor
  • Constructors

class Person(_firstName: String, _lastName: String)
val person = Person("Hans", "Peter")
class Person(_firstName: String, _lastName: String){

  val firstName: String
  val lastName: String

  init{                   // init block, multiple are possible
    firstname = _firstName
    lastname = _lastName
  }
}
val person = Person("Hans", "Peter")
class Person(_firstName: String, _lastName: String){

  val firstName: String = _firstName
  val lastName: String = _lastName
}
val person = Person("Hans", "Peter")
print(person.firstName)
  • Property access syntax, no getter/setters needed.

class Person(val firstName: String, val lastName: String){
}

val person = Person("Hans", "Peter")
print(person.firstName)
  • Secondary constructor

class Person(val firstName: String, val lastName: String){

  constructor(): this("Default", "Name"){
    print("secondary constructor")
  }
}

val person = Person()
print(person.firstName)
  • init vs constructor execution order

class Person(val firstName: String, val lastName: String){

  init{
    print("Init 1")
  }

  constructor(): this("Default", "Name"){
    print("secondary constructor")
  }

  init{
    print("Init 2")
  }
  
}

val person = Person("A", "B") // init 1 and init 2
val person = Person()         // init 1, init 2, secondary constructor
class Person(val firstName: String = "Peter", val lastName: String = "Parker"){


}

val person = Person("A", "B") 
val person = Person()

Class-Properties

  • above read-only properties

class Person(val firstName: String = "Peter", val lastName: String = "Parker"){
  var nickName: String? = null 
}

val person = Person() 
person.nickName = "Bla" // Mutable
  • deafult set/get methods can be overwritten

class Person(val firstName: String = "Peter", val lastName: String = "Parker"){
  var nickName: String? = null
      set(value) {
        field = value
        print("The new nickname is $value")
      }
      get(){
        print("Returning $field")
        return field
      }
}

Class-methods

class Person(val firstName: String = "Peter", val lastName: String = "Parker"){
  var nickName: String? = null
      set(value) {
        field = value
        print("The new nickname is $value")
      }
      get(){
        print("Returning $field")
        return field
      }

    fun printInfo(){
      val nickNameToPrint = if(nickname != null) nickName else "no Nickname"
      print("$firstName $nickNameToPrint $lastName")
    }
}
class Person(val firstName: String = "Peter", val lastName: String = "Parker"){
  var nickName: String? = null
      set(value) {
        field = value
        print("The new nickname is $value")
      }
      get(){
        print("Returning $field")
        return field
      }

    fun printInfo(){
      val nickNameToPrint = nickName ?: " no nickname" // elvis operator
      print("$firstName $nickNameToPrint $lastName")
    }
}

Visibility modifiers

  • public by default

  • internal public for modul

  • private

{private|public|internal} class Person(val firstName: String = "Peter", val lastName: String = "Parker"){
  {public|private|protected} var nickName: String? = null
      set(value) {
        field = value
        print("The new nickname is $value")
      }
      get(){
        print("Returning $field")
        return field
      }

    {public|private|protected} fun printInfo(){
      val nickNameToPrint = nickName ?: " no nickname" // elvis operator
      print("$firstName $nickNameToPrint $lastName")
    }
}

Interfaces

interface PersonInfoProvider{

}

equals

interface PersonInfoProvider
class BasicInfoProvider: PersonInfoProvider {

}
  • Function signature

interface PersonInfoProvider{
  fun printInfo(person: Person)
}

class BasicInfoProvider: PersonInfoProvider {
  
  override fun printInfo(person: Person){
    person.printInfo()
  }
}

val provider - BasicInfoProvider()
provider.printInfo(Person())
  • ☝️interfaces can have default implementations

interface PersonInfoProvider{
  fun printInfo(person: Person){// default implementation
    person.printInfo()
  }
}

class BasicInfoProvider: PersonInfoProvider {
  
}

val provider - BasicInfoProvider()
provider.printInfo(Person())
  • ☝️ interfaces can have properties which can be overwritten

interface PersonInfoProvider{
  val providerInfo: String
  
  fun printInfo(person: Person){
    print(providerInfo)
    person.printInfo()
  }
}

class BasicInfoProvider: PersonInfoProvider {
  override val providerInfo: String
      get() = "BasicInfoProvider"

  override fun printInfo(person: Person){
    super.printInfo()
    print("Additional logic")
  } 
}

val provider - BasicInfoProvider()
provider.printInfo(Person())
  • Implement multiple interfaces

interface SessionInfoProvider{
  fun getSessionId(): String
}

class BasicInfoProvider: PersonInfoProvier, SessionInfoProvider{}
  • Check interface type with is and !is

fun checkTypes(infoProvider: PersonInfoProvider){
    if (infoProvider is SessionInfoProvider){
      print("Also SessionInfoProvider")
    }
}
  • Cast types with as

fun checkTypes(infoProvider: PersonInfoProvider){
    if (infoProvider is SessionInfoProvider){
      (infoProvider as SessionInfoProvider).method()
    }
}