Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Kotlin in 45 minutes

Magda Miu
November 09, 2019

Kotlin in 45 minutes

Kotlin promises concise, expressive and secure code. The presentation will include a full tour of language basics, we will have some fun with functions and will learn new keywords from the Kotlin world. We will discover the main advantages of Kotlin compared to Java and we will explore the inventive features Kotlin offers for working with classes. Finally, we will highlight some advanced topics like delegation and coroutines. This talk is suitable for every developer who is looking for a modern and safe language to use in developing awesome apps.

Magda Miu

November 09, 2019
Tweet

More Decks by Magda Miu

Other Decks in Programming

Transcript

  1. Kotlin in 45 minutes Magda Miu @magdamiu Squad Lead Developer

    at Orange Android Google Developer Expert
  2. What is Kotlin? • General-purpose • FP + OOP •

    Open source (Apache 2.0) • Developed by JetBrains • Static typing
  3. 2010 Project started 2016 Kotlin 1.0 2017 Official on Android

    2018 Kotlin 1.3 2019 Kotlin 1.3.50 Kotlin timeline
  4. Kotlin popularity In the latest Stack Overflow developer survey, it

    ranks as the 4th most loved programming language.
  5. 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
  6. Development tools • JDK ◦ JVM 1.6+ • Kotlin Compiler

    • Editor or IDE ◦ IntelliJ IDEA, Android Studio, NetBeans, Eclipse
  7. *.kt *.java Kotlin compiler Java compiler *.class *.jar App Kotlin

    is 100% interoperable with Java Kotlin runtime
  8. 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
  9. 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}""")
  10. 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.
  11. val number = 0 val result = if (number >

    0) { "Positive number" } else if (number < 0) { "Negative number" } else { "Zero" } println(result) if / else
  12. val number = 0 val result = if (number >

    0) { "Positive number" } else if (number < 0) { "Negative number" } else { "Zero" } println(result) // => Zero if / else
  13. 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
  14. 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
  15. 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
  16. 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
  17. var sum = 234 when (sum) { is Int ->

    println("The sum is $sum") else -> println("It is not an Int") } when with check type
  18. 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
  19. for (index in 1..10) { println(index) } for (index in

    12 downTo 0 step 2) { println(index) } for
  20. 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
  21. while (sumOfNumbers > 0) { sumOfNumbers-- } do { val

    result = retrieveData() } while (result != null) while & do... while
  22. 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
  23. 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.
  24. 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
  25. // 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") }
  26. 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
  27. 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
  28. 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
  29. // Elvis operator val name: String? = null val lengthOfName

    = name?.length ?: -1 println(lengthOfName)
  30. // Elvis operator val name: String? = null val lengthOfName

    = name?.length ?: -1 println(lengthOfName) // => -1
  31. fun add(a: Int, b: Int): Int { return a +

    b } Function name Parameters Return type Function body
  32. // 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
  33. // 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
  34. // 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
  35. // named arguments fun getFullName(firstName: String, lastName: String): String {

    return "$firstName $lastName" } getFullName(lastName = "Miu", firstName = "Magda")
  36. class Utility { // infix functions = functions with a

    single parameter infix fun String.onto(other: String) = Pair(this, other) } fun main(args: Array<String>) { val blueShoes = "blue".onto("shoes") val yellowScarf = "yellow" onto "scarf" println(blueShoes) // => (blue, shoes) println(yellowScarf) // => (yellow, scarf) }
  37. // 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
  38. // 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 }
  39. 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)
  40. val sum: (Int, Int) -> Int = { a, b

    -> a + b } println(sum(3,4))
  41. val sum: (Int, Int) -> Int = { a, b

    -> a + b } println(sum(3,4)) // => 7
  42. // 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))
  43. // 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
  44. 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.
  45. Class • There are primary and secondary constructors. For secondary

    we should add the keyword constructor • The primary constructor cannot contain any code.
  46. 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)
  47. 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
  48. 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(){ } }
  49. // "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 }
  50. 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.
  51. 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() }
  52. 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.
  53. interface Pet { fun eat() fun sleep() } class Cat

    : Pet { override fun eat() { println("Cat eats fish") } override fun sleep() { println("Cat sleeps a lot") } }
  54. Delegation • Composition over Inheritance design pattern • Native support

    for delegation (implicit delegation) • Zero boilerplate code
  55. interface PetAction { fun eat() } interface PetColor { val

    color: String } object YellowColor : PetColor { override val color = "yellow" }
  56. 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
  57. 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
  58. fun delegate() { val kittyCat = Cat() println("Pet has color

    ${kittyCat.color}") kittyCat.eat() } fun main(args: Array<String>) { delegate() } // => Pet has color yellow // => eats a lot of fish
  59. • 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!
  60. 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 }
  61. Companion object • companion object: syntactically it's similar to the

    static methods in Java class Person { companion object { fun callMe() = "Call" } } // Person.callMe()
  62. // 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
  63. // 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
  64. // 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
  65. // 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
  66. 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
  67. 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.
  68. Hello Kotlin import kotlinx.coroutines.* fun main() = runBlocking { launch

    { printKotlin() } println("Hello") } suspend fun printKotlin() { delay(1000L) println("Kotlin") } Example 1
  69. Kotlin Hello import kotlinx.coroutines.* fun main() = runBlocking { printKotlin()

    println("Hello") } suspend fun printKotlin() { delay(1000L) println("Kotlin") } Example 1
  70. 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)
  71. 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