What is Kotlin?
● General-purpose
● FP + OOP
● Open source (Apache 2.0)
● Developed by JetBrains
● Static typing
Slide 5
Slide 5 text
Kotlin Philosophy
To create a modern and pragmatic language for the industry,
not an academic one.
Slide 6
Slide 6 text
2010 Project started
2016 Kotlin 1.0
2017 Official on Android
2018 Kotlin 1.3
2019 Kotlin 1.3.50
Kotlin timeline
Slide 7
Slide 7 text
Kotlin popularity
In the latest Stack Overflow developer survey, it
ranks as the 4th most loved programming
language.
Slide 8
Slide 8 text
Current adoption
Slide 9
Slide 9 text
Build Applications for...
Slide 10
Slide 10 text
Android apps built with Kotlin
Slide 11
Slide 11 text
Conventions
● The same conventions like on Java
● Uppercase for types
● Lower camelCase for methods and properties
● Semicolons are optional
● Reverse notation for packages
○ A file could contain multiple classes
○ The folder names not have to match the package name
Slide 12
Slide 12 text
Development tools
● JDK
○ JVM 1.6+
● Kotlin Compiler
● Editor or IDE
○ IntelliJ IDEA, Android Studio, NetBeans, Eclipse
Slide 13
Slide 13 text
*.kt
*.java
Kotlin
compiler
Java
compiler
*.class *.jar
App
Kotlin is 100% interoperable with Java
Kotlin
runtime
Slide 14
Slide 14 text
Build tools
● Maven
● Gradle
● Kobalt
● Ant
● Command Line
Basic Types
Type Size
Double 64
Float 32
Long 64
Int 32
Short 16
Byte 8
Slide 17
Slide 17 text
val vs
var
● val is immutable (read-only) and
you can only assign a value to
them exactly one time.
● var is mutable and can be
reassigned.
// immediate assignment
val countOfEvenNumbers: Int = 10
// `Int` type is inferred
var sumOfNumbers = 0
// type required when no
initializer is provided
var countOfPrimeNumbers: Int
// deferred assignment
countOfPrimeNumbers = 3
countOfPrimeNumbers = 24
Slide 18
Slide 18 text
String interpolation
● Simple reference uses $
● Complex references uses ${}
● Raw Strings """
val firstWord = "Learn "
val secondWord = "Kotlin"
var bothWords = "$firstWord
$secondWord"
println("$bothWords has
${bothWords.length}")
println(""""$bothWords" has
${bothWords.length}""")
Slide 19
Slide 19 text
Control flow: if, when, for, while
● if - in Kotlin if is an expression, so it returns a value. There is no ternary
operator.
● when - replaces “switch” from Java. We can also check a value for being or
not in a specific range and we can also check if a variable is or not of a
particular type.
● for - iterates through anything that provides an iterator. Can use the
withIndex library function.
● while and do … while - same behaviour like in Java.
Slide 20
Slide 20 text
val number = 0
val result = if (number > 0) {
"Positive number"
} else if (number < 0) {
"Negative number"
} else {
"Zero"
}
println(result)
if / else
Slide 21
Slide 21 text
val number = 0
val result = if (number > 0) {
"Positive number"
} else if (number < 0) {
"Negative number"
} else {
"Zero"
}
println(result) // => Zero
if / else
Slide 22
Slide 22 text
val firstValue = 6
val secondValue = 3
val operator = "/"
val resultOfOperation = when (operator) {
"+" -> firstValue + secondValue
"-" -> firstValue - secondValue
"*" -> firstValue * secondValue
"/" -> firstValue / secondValue
else -> "$operator operator is invalid."
}
println(resultOfOperation)
when
Slide 23
Slide 23 text
val firstValue = 6
val secondValue = 3
val operator = "/"
val resultOfOperation = when (operator) {
"+" -> firstValue + secondValue
"-" -> firstValue - secondValue
"*" -> firstValue * secondValue
"/" -> firstValue / secondValue
else -> "$operator operator is invalid."
}
println(resultOfOperation) // => 2
when
Slide 24
Slide 24 text
var age = 22
when (age) {
in 1..18 -> print("Age is in the range")
!in 18..110 -> print("Age is outside the range")
else -> print("None of the above")
}
when with range
Slide 25
Slide 25 text
var age = 22
when (age) {
in 1..18 -> print("Age is in the range")
!in 18..110 -> print("Age is outside the range")
else -> print("None of the above")
} // => None of the above
when with range
Slide 26
Slide 26 text
var sum = 234
when (sum) {
is Int -> println("The sum is $sum")
else -> println("It is not an Int")
}
when with check type
Slide 27
Slide 27 text
var sum = 234
when (sum) {
is Int -> println("The sum is $sum")
else -> println("It is not an Int")
}// => The sum is 234
when with check type
Slide 28
Slide 28 text
for (index in 1..10) {
println(index)
}
for (index in 12 downTo 0 step 2) {
println(index)
}
for
Slide 29
Slide 29 text
var languages = arrayOf("Java", "Kotlin", "Scala", "C#")
for (item in languages)
println(item)
var desserts = arrayOf("Cupcake", "Ice cream", "Eclair", "Pie")
for (item in desserts.indices) {
if (desserts[item].length > 4)
println(desserts[item])
}
for with index
Slide 30
Slide 30 text
while (sumOfNumbers > 0) {
sumOfNumbers--
}
do {
val result = retrieveData()
} while (result != null)
while & do...
while
Slide 31
Slide 31 text
Equality Checks
In Kotlin we have structural equality (a
check for equals()) ==
val countries = setOf("Java",
"JavaScript", "Swift")
val neighbors = setOf("Swift",
"JavaScript", "Java")
println(countries == neighbors)
// => true
Slide 32
Slide 32 text
No content
Slide 33
Slide 33 text
Null safety
● In an effort to rid the world of NullPointerException, variable types in
Kotlin don't allow the assignment of null.
● In order to use a variable that can be null, declare it nullable by adding ? at
the end of its type.
Slide 34
Slide 34 text
But wait...
The only possible causes of NPE's may be:
● An explicit call to throw NullPointerException()
● Usage of the !! operator (not-null assertion operator)
● Some data inconsistency with regard to initialization
● Java interoperation
Slide 35
Slide 35 text
// check for null in conditions
val trainingName: String? = "Learn Kotlin in 45 minutes"
if (trainingName != null && trainingName.isNotEmpty()) {
print("String of length ${trainingName.length}")
} else {
print("Empty string")
}
Slide 36
Slide 36 text
val platform: String? = null
val language = "Kotlin"
println(platform?.length) // safe call
println(language.length) // unnecessary safe call
val lengthOfWord = platform!!.length // !! operator
val numberOfLetters: Int? = lengthOfWord as? Int // safe cast
Slide 37
Slide 37 text
val platform: String? = null
val language = "Kotlin"
println(platform?.length) // safe call
println(language.length) // unnecessary safe call
val lengthOfWord = platform!!.length // !! operator
val numberOfLetters: Int? = lengthOfWord as? Int // safe cast
Slide 38
Slide 38 text
val platform: String? = null
val language = "Kotlin"
println(platform?.length) // safe call
println(language.length) // unnecessary safe call
val lengthOfWord = platform!!.length // !! operator
val numberOfLetters: Int? = lengthOfWord as? Int // safe cast
Slide 39
Slide 39 text
// Elvis operator
val name: String? = null
val lengthOfName = name?.length ?: -1
println(lengthOfName)
Slide 40
Slide 40 text
// Elvis operator
val name: String? = null
val lengthOfName = name?.length ?: -1
println(lengthOfName) // => -1
// named arguments
fun getFullName(firstName: String, lastName: String): String {
return "$firstName $lastName"
}
getFullName(lastName = "Miu", firstName = "Magda")
Slide 50
Slide 50 text
class Utility {
// infix functions = functions with a single parameter
infix fun String.onto(other: String) = Pair(this, other)
}
fun main(args: Array) {
val blueShoes = "blue".onto("shoes")
val yellowScarf = "yellow" onto "scarf"
println(blueShoes) // => (blue, shoes)
println(yellowScarf) // => (yellow, scarf)
}
Slide 51
Slide 51 text
// functions with varargs parameters
fun varargExample(vararg names: Int) {
println("Argument has ${names.size} elements")
}
varargExample() // => Argument has 0 elements
varargExample(1) // => Argument has 1 elements
varargExample(1, 2, 3) // => Argument has 3 elements
Slide 52
Slide 52 text
// high order function = fun with fun or fun returns a fun
fun add(a: Int, b: Int): Int {
return a + b
}
fun returnAddFunction(): ((Int, Int) -> Int) {
return ::add
}
Slide 53
Slide 53 text
Lambda
● A lambda expression or an anonymous function is a “function literal”, i.e. a
function that is not declared, but passed immediately as an expression
● A lambda expression is always surrounded by curly braces
● Its parameters (if any) are declared before -> (parameter types may be
omitted)
● The body goes after -> (when present)
Slide 54
Slide 54 text
val sum: (Int, Int) -> Int = { a, b -> a + b }
println(sum(3,4))
Slide 55
Slide 55 text
val sum: (Int, Int) -> Int = { a, b -> a + b }
println(sum(3,4)) // => 7
Slide 56
Slide 56 text
// returning from a lambda
val calculateGrade = { grade : Int ->
when(grade) {
in 0..40 -> "Fail"
in 41..70 -> "Pass"
in 71..100 -> "Distinction"
else -> false
}
}
println(calculateGrade(57))
Slide 57
Slide 57 text
// returning from a lambda
val calculateGrade = { grade : Int ->
when(grade) {
in 0..40 -> "Fail"
in 41..70 -> "Pass"
in 71..100 -> "Distinction"
else -> false
}
}
println(calculateGrade(57)) // => Pass
Slide 58
Slide 58 text
Extension functions
● An extension function is a member function of a class that is defined outside
the class.
● Extensions are resolved statically and can also be defined with the class type
that is nullable.
● If a class contains a companion object, then we can also define extension
functions and properties for the companion object.
Slide 59
Slide 59 text
fun String.removeFirstLastChar(): String =
this.substring(1, this.length - 1)
Receiver type
Receiver object
Slide 60
Slide 60 text
fun String.removeFirstLastChar(): String =
this.substring(1, this.length - 1)
println("Kotlin".removeFirstLastChar())
fun reportError(): Nothing {
throw RuntimeException()
}
fun displayHelloMessage(): Unit {
println("Hello from Kotlin! :)")
}
Slide 64
Slide 64 text
fun reportError(): Nothing {
throw RuntimeException()
}
fun displayHelloMessage(): Unit {
println("Hello from Kotlin! :)")
}
Slide 65
Slide 65 text
Basic Data
Types
Numbers
Characters
Booleans
Arrays
Strings
Any
Nothing
Unit
Slide 66
Slide 66 text
Class
● There are primary and secondary constructors. For secondary we should add
the keyword constructor
● The primary constructor cannot contain any code.
Slide 67
Slide 67 text
// primary constructor with fullName property (setter & getter)
class Person(val fullName: String) { /*...*/ }
Slide 68
Slide 68 text
class Person(val fullName: String) {
val age: Int
get() {
return 18
}
// secondary constructor
constructor(fullName: String, age: Int) : this(fullName) {}
}
// instance of the class
val john = Person("John", 24)
Slide 69
Slide 69 text
Package
Visibility modifiers
Modifier Description
public
declarations are visible
everywhere (default one)
private
visible inside the file
containing the declaration
internal
visible inside the same module
(a set of Kotlin files compiled
together)
Class
Modifier Description
public
visible to any client who can
see the declaring class
private visible inside the class only
protected
visible inside the class and its
subclasses
internal
visible to any client inside the
module that can see the
declaring class
Slide 70
Slide 70 text
Inheritance
● Inheritance: use open keyword
for class
● Overriding methods and
properties: use the open modifier
open class Person {
open val name = "Tom"
open fun displaySkills() { }
}
// inheritance and override
class Student : Person() {
override val name = "Jerry"
override fun displaySkills(){ }
}
Slide 71
Slide 71 text
// "object" keyword can be used to create singleton objects.
object TheObject {
fun hello() = "hello"
override fun toString() = "Hello, it's me,
${TheObject::class.simpleName}"
}
fun useSingletonObject() {
println(TheObject.hello()) // => hello
val someRef: Any = TheObject
println(someRef) // => Hello, it's me, TheObject
}
Slide 72
Slide 72 text
Abstract class
● An abstract class cannot be instantiated.
● We can override a non-abstract open member with an abstract one
● Abstract class or abstract function does not need to annotate with open
keyword as they are open by default.
Slide 73
Slide 73 text
abstract class Car {
abstract fun run()
open fun computeTaxes() {}
}
abstract class SafeCar: Car() {
override fun run() {
println("SafeCar is running safely..")
}
override abstract fun computeTaxes()
}
Slide 74
Slide 74 text
Interface
● An interface can have both abstract and non-abstract functions.
● An interface can only have abstract properties (data members)
● A class can implement more than one interface.
● All abstract properties and abstract functions of an interface must be
overridden in the classes that implement it.
Slide 75
Slide 75 text
interface Pet {
fun eat()
fun sleep()
}
class Cat : Pet {
override fun eat() {
println("Cat eats fish")
}
override fun sleep() {
println("Cat sleeps a lot")
}
}
Slide 76
Slide 76 text
Delegation
● Composition over Inheritance design pattern
● Native support for delegation (implicit delegation)
● Zero boilerplate code
Slide 77
Slide 77 text
interface PetAction {
fun eat()
}
interface PetColor {
val color: String
}
object YellowColor : PetColor {
override val color = "yellow"
}
Slide 78
Slide 78 text
class PrintingPetAction(val food: String) : PetAction {
override fun eat() {
println(food)
}
}
class Cat(petColor: PetColor = YellowColor) :
PetAction by PrintingPetAction("eats a lot of fish"),
PetColor by petColor
Slide 79
Slide 79 text
class PrintingPetAction(val food: String) : PetAction {
override fun eat() {
println(food)
}
}
class Cat(petColor: PetColor = YellowColor) :
PetAction by PrintingPetAction("eats a lot of fish"),
PetColor by petColor
Slide 80
Slide 80 text
fun delegate() {
val kittyCat = Cat()
println("Pet has color ${kittyCat.color}")
kittyCat.eat()
}
fun main(args: Array) {
delegate()
}
// => Pet has color yellow
// => eats a lot of fish
Slide 81
Slide 81 text
● Data classes are a concise way to create
classes that just hold data.
Data classes
Function Price
Getters and Setters 0 Lei
equals() & hashCode() 0 Lei
toString() 0 Lei
componentN() 0 Lei
copy() 0 Lei
TOTAL FREE!
Slide 82
Slide 82 text
data class Character(val name: String, val age: Int)
fun main() {
val mickeyMouse = Character("Mickey Mouse", 82)
val mickeyMouseToday = mickeyMouse.copy(age = 83)
// destructuring declarations
val (name, age) = mickeyMouseToday
println("$name, $age years of age")
mickeyMouseToday.component1() // => name
mickeyMouseToday.component2() // => age
}
Slide 83
Slide 83 text
Companion object
● companion object: syntactically
it's similar to the static methods
in Java
class Person {
companion object {
fun callMe() = "Call"
}
}
// Person.callMe()
// immutable list and mutable list
val numbersList = listOf("one", "two", "three")
val mutableNumbersList = mutableListOf("one", "two", "three")
listOf(1, 5, 3).sum() // => 9
listOf("a", "b", "cc").sumBy { it.length } // => 4
List
Slide 88
Slide 88 text
// immutable set and mutable set
val colors = setOf("red", "blue", "yellow")
val mutableColors = mutableSetOf("red", "blue", "yellow")
val longerThan3 = colors.filter { it.length > 3 } // => [blue, yellow]
Set
Slide 89
Slide 89 text
// immutable map and mutable map
val desserts = hashMapOf("whipped cream" to "cake", "chocolate" to
"cookie")
println(desserts["chocolate"])
val inventory = mutableMapOf("pancake" to 1)
inventory.put("cake", 3)
inventory.remove("pancake")
Map
Slide 90
Slide 90 text
// Sequences represent lazily-evaluated collections.
val fooSequence = generateSequence(1, { it + 1 })
val x = fooSequence.take(10).toList()
println(x) // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Sequence
Slide 91
Slide 91 text
Collection vs Sequence
Source: Collections and sequences in Kotlin by
Florina Muntenescu
Suspend functions
● suspend is a keyword that defines the coroutine and it means that the
function could be paused or resumed
● Used inside coroutines like regular functions
● Can call other suspending functions
● Wait tasks to complete
Slide 99
Slide 99 text
Builders
● launch - Launches new coroutine without blocking current thread and
returns a reference to the coroutine as a Job.
● runBlocking - Runs new coroutine and blocks current thread interruptible
until its completion.
● async - Creates new coroutine and returns its future result as an
implementation of Deferred. We can use await to get the result.
Slide 100
Slide 100 text
Hello
Kotlin
import kotlinx.coroutines.*
fun main() = runBlocking {
launch { printKotlin() }
println("Hello")
}
suspend fun printKotlin() {
delay(1000L)
println("Kotlin")
}
Example 1
Slide 101
Slide 101 text
Kotlin
Hello
import kotlinx.coroutines.*
fun main() = runBlocking {
printKotlin()
println("Hello")
}
suspend fun printKotlin() {
delay(1000L)
println("Kotlin")
}
Example 1
Slide 102
Slide 102 text
Main advantages of Kotlin
● Readability
○ A code is clean if it is easy to understand
● Interoperability
○ Q: “Can I use my existing libraries?”
○ A: “Yes, absolutely!”
● Safety
○ Prevents some specific type of errors (NPE)
● Tooling
○ Kotlin is a compiled language (IntelliJ IDEA, Android Studio, NetBeans, Eclipse)
Slide 103
Slide 103 text
Best practices
1. Agree on conventions beforehand
2. Don’t treat it as Java with a different syntax
3. Use a linter (like ktlint)
4. Embrace the immutability
5. Reconsider if you need to use !! operator
6. Don’t hide too much info
7. Choose readable over short expressions
Slide 104
Slide 104 text
Kotlin is about developer happiness
and productivity.
Slide 105
Slide 105 text
Learn more...
Slide 106
Slide 106 text
No content
Slide 107
Slide 107 text
No content
Slide 108
Slide 108 text
No content
Slide 109
Slide 109 text
Thank you!
Magda Miu @magdamiu
Squad Lead Developer at Orange
Android Google Developer Expert