Slide 1

Slide 1 text

Kotlin in 45 minutes Magda Miu @magdamiu Squad Lead Developer at Orange Android Google Developer Expert

Slide 2

Slide 2 text

1 4 3 2 Agenda Introduction Kotlin Basics Functions Classes 5 Kotlin Essentials

Slide 3

Slide 3 text

1 4 3 2 Agenda Introduction Kotlin Basics Functions Classes 5 Kotlin Essentials

Slide 4

Slide 4 text

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

Slide 15

Slide 15 text

1 4 3 2 Agenda Introduction Kotlin Basics Functions Classes 5 Kotlin Essentials

Slide 16

Slide 16 text

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

Slide 41

Slide 41 text

1 4 3 2 Agenda Introduction Kotlin Basics Functions Classes 5 Kotlin Essentials

Slide 42

Slide 42 text

Let’s have some fun

Slide 43

Slide 43 text

// Kotlin syntax for main function fun main() { println("Hello Kotlin!") }

Slide 44

Slide 44 text

fun add(a: Int, b: Int): Int { return a + b } Function name Parameters Return type Function body

Slide 45

Slide 45 text

// equivalent Kotlin syntax fun add(a: Int, b: Int): Int { return a + b } fun add(a: Int, b: Int): Int = a + b fun add(a: Int, b: Int) = a + b

Slide 46

Slide 46 text

// equivalent Kotlin syntax fun add(a: Int, b: Int): Int { return a + b } fun add(a: Int, b: Int): Int = a + b fun add(a: Int, b: Int) = a + b

Slide 47

Slide 47 text

// equivalent Kotlin syntax fun add(a: Int, b: Int): Int { return a + b } fun add(a: Int, b: Int): Int = a + b fun add(a: Int, b: Int) = a + b

Slide 48

Slide 48 text

// default parameter values fun displayTitleAndName(name: String, prefix: String = "dr") { println("$prefix $name") }

Slide 49

Slide 49 text

// 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())

Slide 61

Slide 61 text

fun String.removeFirstLastChar(): String = this.substring(1, this.length - 1) println("Kotlin".removeFirstLastChar()) // => otli

Slide 62

Slide 62 text

1 4 3 2 Agenda Introduction Kotlin Basics Functions Classes 5 Kotlin Essentials

Slide 63

Slide 63 text

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

Slide 84

Slide 84 text

1 4 3 2 Agenda Introduction Kotlin Basics Functions Classes 5 Kotlin Essentials

Slide 85

Slide 85 text

Collections

Slide 86

Slide 86 text

No content

Slide 87

Slide 87 text

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

Slide 92

Slide 92 text

Coroutines

Slide 93

Slide 93 text

Coroutines are lightweight threads

Slide 94

Slide 94 text

Coroutines = Co + Routines Cooperation Functions

Slide 95

Slide 95 text

Single threaded Thread 1 Task 1 Task 2 Task 3 Task 4

Slide 96

Slide 96 text

Multiple threaded Thread 1 Task 1 Task 3 Thread 2 Task 2 Task 4

Slide 97

Slide 97 text

Coroutine Thread 1 Task 1 Task 3 Thread 2 Task 2 Task 4 Result

Slide 98

Slide 98 text

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