Kotlin programming language
Kotlin programming language
Introduction

Kotlin programming language

Introduction to Kotlin



  1. History, Why, What?
  2. The Basic Syntax
  3. Variables & Constants
  4. Functions
  5. Conditional Statements
  6. Loops
  7. Nullability
  8. Extension Functions
  9. Extension Properties
  10. Infix Functions
Kotlin programming language

History, Why, What?

Kotlin

Kotlin programming language

What is Kotlin?

  • Statically-typed programming language
  • Kotlin apps are primarily language for a Java Virtual Machine (JVM)
  • Supports both Object-oriented and Functional programming paradigms
  • Development started in 2010 by JetBrains
  • Announced as official language for Android in May of 2017
  • Executed in following targets:
    • Mobile (Android, iOS)
    • Backend
    • Web
    • Desktop
Kotlin programming language

Why Kotlin

  • Open Source
  • Expressive, Concise and Pragmatic
  • Type Safety
  • Portability/Compatibility
  • High Quality IDE Support
  • Community
  • Android
  • More than a gazillion devices run Java Kotlin
Kotlin programming language

What about AI?

Kotlin programming language

The Basic Syntax

Kotlin

Kotlin programming language

Hello, world!

fun main() {
    println("Hello, world!")
}
fun main() = println("Hello, world!")
fun main(args: Array<String>) { // Run > Edit Configurations → Program arguments
    println("Hello")
    println(args.joinToString(", "))
}
fun main(args: Array<String>) {
    println("Hello"); // <-- ⚠ Semicolon not needed in Kotlin!
    println(args.joinToString(", "))
}
Kotlin programming language

The basics

fun main(args: Array<String>) {
    print("Hello")
    println(", world!")
}
  • an entry point of a Kotlin application is the main top-level function
  • it accepts a variable number of String arguments that can be omitted
  • print prints its argument to the standard output
  • println prints its arguments and adds a line break
Kotlin programming language

Variables & constants

Kotlin

Kotlin programming language

Read-only and mutable variables

val/var myValue: Type = someValue
  • var - mutable
  • val - immutable
  • Type can be inferred in most cases
  • assignment can be deferred
Kotlin programming language

Read-only and mutable variables #2

val a: Int = 1		// immediate assignment
val newA = 1		// 'Int' type is inferred
newA = 4                // ❌ Error: Val cannot be reassigned

var b = 2               // 'Int' type is inferred
b = a 			// Reassigning to 'var' is okay
b = "Some other type"   // ❌ Error: Inferred type was String but Int was expected

val c: Int              // Type required when no initializer is provided
c = 3                   // Deferred assignment
a = 4                   // ❌ Error: Val cannot be reassigned
Kotlin programming language

Compile-time constants

const val myValue: Type = someValue
  • const val - compile-time const value
  • val - immutable value
  • for const val use uppercase: MYVALUE
const val NAME = "Kotlin"            // can be calculated at compile-time
val nameLowered = NAME.lowercase()   // cannot be calculated at compile-time
Kotlin programming language

Compile-time constants

  • must be one of:
    • top-level property
    • member of an object declaration
    • member of a companion object
  • must be initialized with a value of type String or a primitive type (Int, Long, Short, Byte, Char, Boolean, Float, Double)
  • cannot be a custom getter
Kotlin programming language

Functions

Kotlin

Kotlin programming language

Functions

fun sum(a: Int, b: Int): Int {
  return a + b
}
  • defined with a fun keyword followed by function name
  • parameters are defined using Pascal notation - name: type
  • parameters are read-only
  • return type is defined in the end
Kotlin programming language

Functions - Expression body

fun sum(a: Int, b: Int): Int = a + b

When the function body consists of a single expression
the curly braces can be omitted and body can be specified after = symbol

Kotlin programming language

Functions - invocation

fun sum(a: Int, b: Int): Int = a + b

sum(1, 2)     // <-- Function invocation

fun main(args: Array<String>) {
    println(sum(1, 2))
}
Kotlin programming language

Functions - named arguments

fun sum(a: Int, b: Int): Int = a + b

sum(a = 1, b = 2)   // invocation with named arguments

sum(b = 2, a = 1)   // order of arguments can be changed

sum(1, b = 2)       // mixing positional and named arguments
Kotlin programming language

Functions - default argument values

fun sum(a: Int = 0, b: Int = 0): Int = a + b

sum(1)      // passes 1 for `a`, uses default value for `b`, returns 1

sum(b = 2)  // passes 2 for `b`, uses default value for `a`, returns 2

sum()       // uses default value for both `a` and `b`,      returns 0
Kotlin programming language

Functions - Unit return type

fun myPrint(text: String): Unit = println(text)
  • Unit is a type
  • Unit means that the function does not return anything meaningful
fun myPrint(text: String) = println(text)
  • return type Unit can be omitted
Kotlin programming language

Functions - Summary

fun mul(a: Int, b: Int): Int {
    return a * b
}

fun mul(a: Int, b: Int) = a * b      // single expression function reduced

fun printMul(a: Int, b: Int): Unit {
    println(mul(a, b))
}

fun printMul(a: Int = 1, b: Int) {   // Unit can be omitted
    println(mul(a, b))
}

fun printMul(a: Int, b: Int = 1) = println(mul(a, b))
Kotlin programming language

Conditional Statements

Kotlin

Kotlin programming language

if expression

// block body variant
fun max(a: Int, b: Int): Int {
    if (a > b) {
        return a
    } else {
        return b
    }
}
fun max(a: Int, b: Int): Int {
    return if (a > b) a else b
}
// expression body variant
fun max(a: Int, b: Int): Int =
    if (a > b) {
        a
    } else {
        b
    }
fun max(a: Int, b: Int) = 
    if (a > b) a else b 
// same as ternary operator ?:
Kotlin programming language

if expression #2

fun max(a: Int, b: Int) =
    if (a > b) {
        println("first branch")
        a 			// `a` is result of if statement block 
    } else {
        println("second branch")
        b			// `b` is result of if statement else block
    }

If if statement body is not a single expression
the last expression in the if statement body evaluates as its return value

Kotlin programming language

when expression

when (x) {
    1 -> print("x == 1")
    2 -> print("x == 2")
    else -> {
        print("x is neither 1 nor 2")
    }
}

when returns the same way if does

when {
    x < 0 -> print("x < 0")
    x > 0 -> print("x > 0")
    else -> {
        print("x == 0")
    }
}

condition can be inside of branches

Kotlin programming language

when statement

enum class Role {
    PROFESSOR, ASSISTANT, STUDENT
}

val role = Role.PROFESSOR

val result = when (role) {
    Role.PROFESSOR, Role.ASSISTANT -> "Access Granted"
    Role.STUDENT -> error("Student can’t modify the course.")
}

when can accept several options in one branch

else branch can be omitted if when block is used as a statement

Kotlin programming language

Boolean operators

Kotlin supports following boolean operators:

  • || – disjunction (logical OR)
  • && – conjunction (logical AND)
  • ! – negation (logical NOT)

There are also extension function counter parts that can be used:

  • or – disjunction (logical OR)
  • and – conjunction (logical AND)
  • not – negation (logical NOT)
Kotlin programming language

Boolean operators - && vs and

if (a && b) { ... }

VS

if (a and b) { ... }

&& - performs short-circuit evaluation
and - infix function, evaluates both arguments

if (a || b) { ... }

VS

if (a or b) { ... }

or - both arguments are evaluated as well

Kotlin programming language

Loops

Kotlin

Kotlin programming language

while loop

val items = listOf("apple", "banana", "kiwi")

var index = 0
while (index < items.size) {
    println("item at $index is ${items[index]}")
    index++
}

var toComplete: Boolean
do {
    ...
    toComplete = ...
} while(toComplete)

The condition variable can be initialized inside of the do…while loop.

Kotlin programming language

Ranges

val intRange: IntRange = 1..10          // sequence from 1 to 10 
val charRange: CharRange = 'a'..'z'     // sequence from `a` to `z`
val longRange: LongRange = 1L..10L
  • Range is interval between two values, defined using .. operator
  • Range is closed and inclusive - second value is always part of the range
  • Ranges can be defined with: Int, Char, Long
  • These ranges can be treated as arithmetic progressions
  • Arithmetic progression: difference between successive members remains constant
Kotlin programming language

Ranges - iteration

for (x in 1..5) {
    print(x)
}
  • Iterates over sequence of numbers from 1 to 5
  • Expression 1..5 defines a range from 1 to 5
for (x in 1 until 5) {
    print(x)
}
  • Iterates over sequence of numbers from 1 to 4
  • Expression 1 until 5 defines a range from 1 to 4
Kotlin programming language

Ranges - iteration #2

for (x in 9 downTo 0) {
    print(x)
}

Java

for (int x=9; x>=0; x--) {
    System.out.print(x);
}
  • 9 downTo 0 creates a sequence of numbers from 9 to 0
  • downTo is an extension function, not a keyword
  • .. operator actually invokes T.rangeTo(that:T) extension function
Kotlin programming language

Ranges - iteration #3

for (x in 9 downTo 0 step 3) {
    print(x)
}

Java

for (int x=9; x>=0; x=x-3) {
    System.out.print(x);
}

step is an extension function that defines the step of the progression

Kotlin programming language

for loop

Iterating over collections

val items = listOf("apple", "banana", "kiwi")

for (item in items) {
    println(item)
}
  • for loop uses semantics “for every item in the list”
  • in for loop, variable declaration is followed by in keyword
    then by collection we want to iterate through
  • item variable type is inferred by compiler
Kotlin programming language

for loop #2

Iterating over collections with index

val items = listOf("apple", "banana", "kiwi")

for ((index, item) in items.withIndex()) {
    println("item at $index is $item")
}

withIndex() function returns a sequence of IndexedValue
which contains both index and value

Kotlin programming language

Nullability

Kotlin

Kotlin programming language

Kotlin handles nullability in compile time
instead of making it a runtime problem

Kotlin programming language

Nullable types are part of the Kotlin type system

Kotlin programming language

Nullable types

val notNullText: String = “Not Null String”
val notNullText: String = null   // Error: Null can not be a value

null can’t be assigned to a variable of not nullable String type

val possiblyNullText: String? = null    // All good

? after type indicates that the variable can hold null value

val possiblyNullText2: String? = ”Can be a null or not null
Kotlin programming language

In the bytecode, Nullable types are represented
with a @Nullable and @NotNull annotations.

Kotlin programming language

Dealing with Nullable types

val nullableText: String? = null

nullableText.length()   // Error: Compile time error - unsafe access
if (nullableText != null) {
   nullableText.length()     // Safe to access, smart casting
}

smartcast works only for a local variables or a global read-only variables.

nullableText?.length()     // Safe to access
Kotlin programming language

Safe Call Operator ?.

someThing?.otherThing // does not throw an NPE if someThing is null
fun printDepartmentHead(employee: Employee) {
    println(employee.department?.head?.name)
}

Safe calls are useful in chains

employee.department?.head?.name?.let { println(it) }

To print only for non-null values, you can use the safe call operator together with let

Kotlin programming language

Dealing with Nullable types

val text: String? = null
val length: Int? = text?.length()  // returns length or null

equivalent to

val length: Int? = if (text != null) text.length() else null

Elvis operator ?:

val length: Int = text?.length() ?: 0    // returns length or 0
val length: Int = if (text != null) text.length() else 0
Kotlin programming language

Elvis operator ?:


If the expression to the left of ?: is not null, it is returned
otherwise, expression to the right is returned

Note that the expression on the RHS is evaluated only if the LHS is null

Kotlin programming language

Unsafe calls

The not-null assertion operator !! converts any value to a non-null type
and throws an NPE exception if the value is null

fun printDepartmentHead(employee: Employee) {
    println(employee.department!!.head!!.name!!)
}

Please, avoid using unsafe calls!!

Kotlin programming language

Extension Functions

Kotlin

Kotlin programming language

Kotlin provides the ability to extend a class
or an interface with new functionality without having to inherit from the class

Kotlin programming language

Extension Functions

fun Int.downTo(to: Int): IntProgression {
    return IntProgression.fromClosedRange(this, to, -1)
}
  • Int type extended with a downTo method
  • extended type is called a receiver
  • receiver is referred to as this
10.downTo(1)

Invoked by stating value of receiver type, followed by . and function invocation

Kotlin programming language

Extension functions #2

  • can extend any type
  • do not modify class they extend
  • no access to private properties of extended type class
  • can not override the member functions
  • resolved statically
Kotlin programming language

Extension Properties

Kotlin

Kotlin programming language

Extension Properties

val List<Int>.lastIndex : Int
    get() = this.size - 1

listOf(1, 2, 3).lastIndex
  • List<Int> extended with a lastIndex extension property
  • extended type is called a receiver
  • in the extension property getter/setter, receiver is referred to as this
  • resolved statically and have no access to private members of extended type
Kotlin programming language

Infix Functions

Kotlin

Kotlin programming language

Infix Functions

infix fun Int.downTo(to: Int): IntProgression {
    return IntProgression.fromClosedRange(this, to, -1)
}

  • declared with infix modifier
  • specific invocation syntax
10 downTo 1
Kotlin programming language

When in ...doubt

Kotlin programming language

Thanx!