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

Top 10 Kotlin Stack Overflow Questions (Kotlin Budapest User Group meetup - May)

Top 10 Kotlin Stack Overflow Questions (Kotlin Budapest User Group meetup - May)

A selection of some of the most frequent questions about Kotlin on Stack Overflow, asked, answered and explained. Something in there for everyone, from beginners to experts.

Marton Braun

May 17, 2018
Tweet

More Decks by Marton Braun

Other Decks in Programming

Transcript

  1. TOP 10 KOTLIN
    STACK OVERFLOW
    QUESTIONS
    Márton Szabolcs Braun
    zsmb.co zsmb13
    [email protected]

    View Slide

  2. Why do this talk?

    View Slide

  3. Why do this talk?

    View Slide

  4. Array vs
    IntArray
    What’s the difference? When do I use which one?

    View Slide

  5. Array vs IntArray

    View Slide

  6. Array vs IntArray
    Array

    View Slide

  7. Array vs IntArray
    Array Integer[]

    View Slide

  8. Array vs IntArray
    Array Integer[]
    val arrayOfInts: Array = arrayOf(1, 2, 3, 4, 5)

    View Slide

  9. Array vs IntArray
    Array Integer[]
    IntArray
    val arrayOfInts: Array = arrayOf(1, 2, 3, 4, 5)

    View Slide

  10. Array vs IntArray
    Array Integer[]
    IntArray int[]
    val arrayOfInts: Array = arrayOf(1, 2, 3, 4, 5)

    View Slide

  11. Array vs IntArray
    Array Integer[]
    IntArray int[]
    val intArray: IntArray = intArrayOf(1, 2, 3, 4, 5)
    val arrayOfInts: Array = arrayOf(1, 2, 3, 4, 5)

    View Slide

  12. Array vs IntArray

    View Slide

  13. Array vs IntArray
    • IntArray

    View Slide

  14. Array vs IntArray
    • IntArray
     Avoids boxing

    View Slide

  15. Array vs IntArray
    • IntArray
     Avoids boxing
     Easier to initialize
    val intArray = IntArray(10)
    val arrayOfInts = Array(5) { i -> i * 2 }

    View Slide

  16. Array vs IntArray
    • IntArray
     Avoids boxing
     Easier to initialize
    • Array
    val intArray = IntArray(10)
    val arrayOfInts = Array(5) { i -> i * 2 }

    View Slide

  17. Array vs IntArray
    • IntArray
     Avoids boxing
     Easier to initialize
    • Array
     Might be required by an API
    val intArray = IntArray(10)
    val arrayOfInts = Array(5) { i -> i * 2 }

    View Slide

  18. Array vs IntArray
    • IntArray
     Avoids boxing
     Easier to initialize
    • Array
     Might be required by an API
     Can store nullable values
    val intArray = IntArray(10)
    val arrayOfInts = Array(5) { i -> i * 2 }
    val notPeople: Array = arrayOfNulls(13)

    View Slide

  19. Iterable vs
    Sequence
    What’s the difference? When do I use which one?

    View Slide

  20. Iterable vs Sequence

    View Slide

  21. Iterable vs Sequence
    Iterable

    View Slide

  22. Iterable vs Sequence
    Iterable java.lang.Iterable

    View Slide

  23. Iterable vs Sequence
     Eager evaluation
    Iterable java.lang.Iterable

    View Slide

  24. Iterable vs Sequence
     Eager evaluation
    Iterable java.lang.Iterable
    val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)

    View Slide

  25. Iterable vs Sequence

    View Slide

  26. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  27. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  28. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  29. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  30. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  31. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  32. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  33. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  34. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  35. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  36. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  37. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  38. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  39. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  40. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  41. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  42. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  43. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  44. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  45. val people: List = getPeople()
    val allowedEntrance = people
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    Iterable vs Sequence

    View Slide

  46. Iterable vs Sequence

    View Slide

  47. Iterable vs Sequence
    Sequence

    View Slide

  48. Iterable vs Sequence
    Sequence
     Lazy evaluation

    View Slide

  49. Iterable vs Sequence
    Sequence
     Lazy evaluation
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  50. Iterable vs Sequence
    Sequence
     Lazy evaluation
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  51. Iterable vs Sequence

    View Slide

  52. Iterable vs Sequence
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  53. Iterable vs Sequence
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  54. Iterable vs Sequence
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  55. Iterable vs Sequence
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  56. Iterable vs Sequence
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  57. Iterable vs Sequence
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  58. Iterable vs Sequence
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  59. Iterable vs Sequence
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  60. Iterable vs Sequence
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  61. Iterable vs Sequence
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  62. Iterable vs Sequence
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  63. Iterable vs Sequence
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  64. Iterable vs Sequence
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  65. Iterable vs Sequence
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  66. Iterable vs Sequence
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  67. Iterable vs Sequence
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  68. Iterable vs Sequence
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  69. Iterable vs Sequence
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  70. Iterable vs Sequence
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  71. Iterable vs Sequence
    val people: List = getPeople()
    val allowedEntrance = people.asSequence()
    .filter { it.age >= 21 }
    .map { it.name }
    .take(5)
    .toList()

    View Slide

  72. Iterable vs Sequence
    Sequence
     Lazy evaluation

    View Slide

  73. Iterable vs Sequence
    Sequence
     Lazy evaluation
     Potentially infinite

    View Slide

  74. Iterable vs Sequence
    Sequence
     Lazy evaluation
     Potentially infinite
    generateSequence(1) { n -> n * 2 }
    .take(20)
    .forEach(::println)

    View Slide

  75. Iterable vs Sequence

    View Slide

  76. Iterable vs Sequence
    • Iterable

    View Slide

  77. Iterable vs Sequence
    • Iterable
     Use by default

    View Slide

  78. Iterable vs Sequence
    • Iterable
     Use by default
     Usually the best choice

    View Slide

  79. Iterable vs Sequence
    • Iterable
     Use by default
     Usually the best choice
    • Sequence

    View Slide

  80. Iterable vs Sequence
    • Iterable
     Use by default
     Usually the best choice
    • Sequence
     To handle an infinite number of elements

    View Slide

  81. Iterable vs Sequence
    • Iterable
     Use by default
     Usually the best choice
    • Sequence
     To handle an infinite number of elements
     For huge collections, judiciously

    View Slide

  82. Iterable vs Sequence
    • Iterable
     Use by default
     Usually the best choice
    • Sequence
     To handle an infinite number of elements
     For huge collections, judiciously
    • Stream

    View Slide

  83. Iterable vs Sequence
    • Iterable
     Use by default
     Usually the best choice
    • Sequence
     To handle an infinite number of elements
     For huge collections, judiciously
    • Stream
     When interoperating with Java

    View Slide

  84. Iteration
    How can / should I iterate over collections?

    View Slide

  85. Iteration

    View Slide

  86. Iteration
    for (i in 0..args.size - 1) {
    println(args[i])
    }

    View Slide

  87. Iteration
    for (i in 0..args.size - 1) {
    println(args[i])
    }
    for (i in 0..args.lastIndex) {
    println(args[i])
    }

    View Slide

  88. Iteration
    for (i in 0..args.size - 1) {
    println(args[i])
    }
    for (i in 0..args.lastIndex) {
    println(args[i])
    }
    for (i in 0 until args.size) {
    println(args[i])
    }

    View Slide

  89. Iteration
    for (i in 0..args.size - 1) {
    println(args[i])
    }
    for (i in 0..args.lastIndex) {
    println(args[i])
    }
    for (i in 0 until args.size) {
    println(args[i])
    }
    for (i in args.indices) {
    println(args[i])
    }

    View Slide

  90. Iteration
    for (i in 0..args.size - 1) {
    println(args[i])
    }
    for (i in 0..args.lastIndex) {
    println(args[i])
    }
    for (i in 0 until args.size) {
    println(args[i])
    }
    for (i in args.indices) {
    println(args[i])
    }
    for (arg in args) {
    println(arg)
    }

    View Slide

  91. Iteration
    for (i in 0..args.size - 1) {
    println(args[i])
    }
    for (i in 0..args.lastIndex) {
    println(args[i])
    }
    for (i in 0 until args.size) {
    println(args[i])
    }
    for (i in args.indices) {
    println(args[i])
    }
    for (arg in args) {
    println(arg)
    }
    args.forEach { arg ->
    println(arg)
    }

    View Slide

  92. Iteration
    for (i in 0..args.size - 1) {
    println(args[i])
    }
    for (i in 0..args.lastIndex) {
    println(args[i])
    }
    for (i in 0 until args.size) {
    println(args[i])
    }
    for (i in args.indices) {
    println(args[i])
    }
    for (arg in args) {
    println(arg)
    }
    args.forEach { arg ->
    println(arg)
    }

    View Slide

  93. Iteration
    for (i in 0..args.size - 1) {
    println(args[i])
    }
    for (i in 0..args.lastIndex) {
    println(args[i])
    }
    for (i in 0 until args.size) {
    println(args[i])
    }
    for (i in args.indices) {
    println(args[i])
    }
    for (arg in args) {
    println(arg)
    }
    args.forEach { arg ->
    println(arg)
    }

    View Slide

  94. Iteration with indexes
    How can I get both the current index and element?

    View Slide

  95. Iteration with indexes
    for ((index, arg) in args.withIndex()) {
    println("$index: $arg")
    }

    View Slide

  96. Iteration with indexes
    for ((index, arg) in args.withIndex()) {
    println("$index: $arg")
    }
    args.forEachIndexed { index, arg ->
    println("$index: $arg")
    }

    View Slide

  97. Iteration with indexes
    for ((index, arg) in args.withIndex()) {
    println("$index: $arg")
    }
    args.forEachIndexed { index, arg ->
    println("$index: $arg")
    }

    View Slide

  98. Iteration with indexes
    for ((index, arg) in args.withIndex()) {
    println("$index: $arg")
    }
    args.forEachIndexed { index, arg ->
    println("$index: $arg")
    }

    View Slide

  99. SAM conversions
    What are SAM conversions?

    View Slide

  100. SAM conversions

    View Slide

  101. SAM conversions
    public interface OnClickListener {
    void onClick(Button button);
    }

    View Slide

  102. SAM conversions
    public interface OnClickListener {
    void onClick(Button button);
    }
    public class Button {
    public void setListener(OnClickListener listener) {
    ...
    }
    }

    View Slide

  103. SAM conversions

    View Slide

  104. SAM conversions
    button.setListener(object : OnClickListener {
    override fun onClick(button: Button?) {
    println("Clicked!")
    }
    })

    View Slide

  105. SAM conversions
    button.setListener(object : OnClickListener {
    override fun onClick(button: Button?) {
    println("Clicked!")
    }
    })
    button.setListener {
    println("Clicked!")
    }

    View Slide

  106. SAM conversions
    button.setListener(object : OnClickListener {
    override fun onClick(button: Button?) {
    println("Clicked!")
    }
    })
    button.setListener {
    println("Clicked!")
    }

    View Slide

  107. SAM conversions
    button.setListener(object : OnClickListener {
    override fun onClick(button: Button?) {
    println("Clicked!")
    }
    })
    button.setListener { button: Button? ->
    println("Clicked!")
    }

    View Slide

  108. SAM conversions #1
    Why are my listeners not being called?

    View Slide

  109. SAM conversions #1
    button.setListener {
    object : OnClickListener {
    override fun onClick(button: Button) {
    println("Clicked!")
    }
    })
    }

    View Slide

  110. SAM conversions #1
    button.setListener {
    object : OnClickListener {
    override fun onClick(button: Button) {
    println("Clicked!")
    }
    })
    }

    View Slide

  111. SAM conversions #1
    button.setListener(object : OnClickListener {
    override fun onClick(button: Button?) {
    object : OnClickListener {
    override fun onClick(button: Button) {
    println("Clicked!")
    }
    })
    }
    })

    View Slide

  112. SAM conversions #1
    button.setListener(object : OnClickListener {
    override fun onClick(button: Button?) {
    val listener = object : OnClickListener {
    override fun onClick(button: Button) {
    println("Clicked!")
    }
    })
    }
    })

    View Slide

  113. SAM conversions #1
    button.setListener(object : OnClickListener {
    override fun onClick(button: Button?) {
    val listener = object : OnClickListener {
    override fun onClick(button: Button) {
    println("Clicked!")
    }
    })
    listener.onClick(...)
    }
    })

    View Slide

  114. SAM conversions #1
    button.setListener(object : OnClickListener {
    override fun onClick(button: Button?) {
    object : OnClickListener {
    override fun onClick(button: Button) {
    println("Clicked!")
    }
    })
    }
    })

    View Slide

  115. SAM conversions #1
    button.setListener {
    object : OnClickListener {
    override fun onClick(button: Button) {
    println("Clicked!")
    }
    })
    }

    View Slide

  116. SAM conversions #1
    button.setListener {
    object : OnClickListener {
    override fun onClick(button: Button) {
    println("Clicked!")
    }
    })
    }
    button.setListener {
    fun onClick(button: Button) {
    println("Clicked!")
    }
    }

    View Slide

  117. SAM conversions #2
    How do I reference my listener instance?

    View Slide

  118. SAM conversions #2
    • What if I need to reference the listener instance?
    button.setListener {
    button.removeListener(this)
    }

    View Slide

  119. SAM conversions #2
    • What if I need to reference the listener instance?
    button.setListener(object: OnClickListener {
    override fun onClick(button: Button) {
    button.removeListener(this)
    }
    })
    button.setListener {
    button.removeListener(this)
    }

    View Slide

  120. SAM conversions #3
    Why am I getting a return type error?

    View Slide

  121. SAM conversions #3
    public interface OnClickListener {
    void onClick(Button button);
    }

    View Slide

  122. SAM conversions #3
    public interface OnClickListener {
    boolean onClick(Button button);
    }

    View Slide

  123. SAM conversions #3
    public interface OnClickListener {
    boolean onClick(Button button);
    }
    button.setListener {
    println("Clicked!")
    }

    View Slide

  124. SAM conversions #3
    public interface OnClickListener {
    boolean onClick(Button button);
    }
    button.setListener {
    println("Clicked!")
    }
    Kotlin: Type mismatch: inferred type is Unit but
    Boolean was expected

    View Slide

  125. SAM conversions #3
    public interface OnClickListener {
    boolean onClick(Button button);
    }
    button.setListener {
    println("Clicked!")
    true
    }

    View Slide

  126. SAM conversions #3
    public interface OnClickListener {
    boolean onClick(Button button);
    }
    button.setListener {
    println("Clicked!")
    true
    }

    View Slide

  127. SAM conversions #4
    What if my interface/method is not written in Java?

    View Slide

  128. SAM conversions #4
    • SAM constructor
    button.setListener(OnClickListener {
    println("Clicked!")
    })

    View Slide

  129. SAM conversions #4
    • SAM constructor
    button.setListener(OnClickListener {
    println("Clicked!")
    })
    Java interface Kotlin interface
    Java method SAM conversion Object expression
    Kotlin method SAM constructor Object expression

    View Slide

  130. Replacing statics #1
    How do I create static functions and variables in Kotlin?

    View Slide

  131. Replacing statics
    class Foo {
    companion object {
    fun x() { ... }
    }
    fun y() { ... }
    }

    View Slide

  132. Replacing statics
    class Foo {
    companion object {
    fun x() { ... }
    }
    fun y() { ... }
    }
    Foo.x()

    View Slide

  133. Replacing statics
    class Foo {
    companion object {
    fun x() { ... }
    }
    fun y() { ... }
    }
    object Foo {
    fun x() { ... }
    }
    Foo.x()
    Foo.x()

    View Slide

  134. Replacing statics
    class Foo {
    companion object {
    fun x() { ... }
    }
    fun y() { ... }
    }
    object Foo {
    fun x() { ... }
    }
    fun x() { ... }
    Foo.x()
    Foo.x()
    x()

    View Slide

  135. Replacing statics
    class Foo {
    companion object {
    fun x() { ... }
    }
    fun y() { ... }
    }
    object Foo {
    fun x() { ... }
    }
    fun x() { ... }
    Foo.x()
    Foo.x()
    x()

    View Slide

  136. Function declaration reference
    Declaration Kotlin usage Java usage
    Companion object Foo.f() Foo.Companion.f();
    Companion object with @JvmStatic Foo.f() Foo.f();
    Object Foo.f() Foo.INSTANCE.f();
    Object with @JvmStatic Foo.f() Foo.f();
    Top level function f() UtilKt.f();
    Top level function with @JvmName* f() Util.f();
    * With the @JvmName annotation on the file use-site target

    View Slide

  137. Variable declaration reference
    Declaration Kotlin usage Java usage
    Companion object X.x X.Companion.getX();
    Companion object with @JvmStatic X.x X.getX();
    Companion object with @JvmField X.x X.x;
    Companion object with const X.x X.x;
    Object X.x X.INSTANCE.getX();
    Object with @JvmStatic X.x X.getX();
    Object with @JvmField X.x X.x;
    Object with const X.x X.x;
    Top level variable x ConstKt.getX();
    Top level variable with @JvmField x ConstKt.x;
    Top level variable with const x ConstKt.x;
    Top level variable with @JvmName* x Const.getX();
    Top level variable with @JvmName* and @JvmField x Const.x;
    Top level variable with @JvmName* and const x Const.x;
    * With the @JvmName annotation on the file use-site target

    View Slide

  138. Replacing statics #2
    What about static initializers?

    View Slide

  139. Static initializers
    class X {
    companion object {
    init {
    println("Static initialization!")
    }
    }
    }

    View Slide

  140. Smart casts on
    mutable properties
    Why are smart casts not working?

    View Slide

  141. Smart casts on mutable properties
    class Dog(var toy: Toy? = null) {
    fun play() {
    if (toy != null) {
    toy.chew()
    }
    }
    }

    View Slide

  142. Smart casts on mutable properties
    class Dog(var toy: Toy? = null) {
    fun play() {
    if (toy != null) {
    toy.chew()
    }
    }
    }
    Kotlin: Smart cast to 'Toy' is impossible, because 'toy' is
    a mutable property that could have been changed by this time

    View Slide

  143. Smart casts on mutable properties
    class Dog(val toy: Toy? = null) {
    fun play() {
    if (toy != null) {
    toy.chew()
    }
    }
    }

    View Slide

  144. Smart casts on mutable properties
    class Dog(var toy: Toy? = null) {
    fun play() {
    if (toy != null) {
    toy.chew()
    }
    }
    }

    View Slide

  145. Smart casts on mutable properties
    class Dog(var toy: Toy? = null) {
    fun play() {
    val _toy = toy
    if (_toy != null) {
    _toy.chew()
    }
    }
    }

    View Slide

  146. Smart casts on mutable properties
    class Dog(var toy: Toy? = null) {
    fun play() {
    toy?.let {
    it.chew()
    }
    }
    }

    View Slide

  147. Smart casts on mutable properties
    class Dog(var toy: Toy? = null) {
    fun play() {
    toy?.chew()
    }
    }

    View Slide

  148. Smart casts on mutable properties
    class Dog(var toy: Toy? = null) {
    fun play() {
    toy?.let {
    it.chew()
    it.chew()
    it.chew()
    }
    }
    }

    View Slide

  149. null!!
    Why am I getting NullPointerExceptions?

    View Slide

  150. null!!

    View Slide

  151. null!!
    class Episode {
    var airdate: Date = null!!
    }

    View Slide

  152. null!!
    class Episode {
    var airdate: Date = null!!
    }
    fun getWeekDay(date: Date?): WeekDay {
    return date!!.getWeekDay()
    }

    View Slide

  153. null!!
    class Episode {
    var airdate: Date = null!!
    }
    fun getWeekDay(date: Date?): WeekDay {
    return date!!.getWeekDay()
    }
    Date?

    View Slide

  154. null!!
    class Episode {
    var airdate: Date = null!!
    }
    fun getWeekDay(date: Date?): WeekDay {
    return date!!.getWeekDay()
    }
    WeekDay
    Date?

    View Slide

  155. null!!
    class Episode {
    var airdate: Date = null!!
    }
    fun getWeekDay(date: Date?): WeekDay {
    return date!!.getWeekDay()
    }
    Date
    WeekDay
    Date?

    View Slide

  156. null!!
    class Episode {
    var airdate: Date = null!!
    }
    fun getWeekDay(date: Date?): WeekDay {
    return date!!.getWeekDay()
    }
    Date

    View Slide

  157. null!!
    class Episode {
    var airdate: Date = null!!
    }
    fun getWeekDay(date: Date?): WeekDay {
    return date!!.getWeekDay()
    }
    Date date as Date

    View Slide

  158. null!!
    class Episode {
    var airdate: Date = null!!
    }
    fun getWeekDay(date: Date?): WeekDay {
    return date!!.getWeekDay()
    }
    Date date as Date
    throw NullPointerException()

    View Slide

  159. null!!
    class Episode {
    var airdate: Date = null!!
    }
    fun getWeekDay(date: Date?): WeekDay {
    return date!!.getWeekDay()
    }
    Date

    View Slide

  160. null!!
    class Episode {
    var airdate: Date = null!!
    }

    View Slide

  161. null!!
    class Episode {
    var airdate: Date = null!!
    }

    View Slide

  162. null!!
    class Episode {
    var airdate: Date = throw KotlinNullPointerException()
    }

    View Slide

  163. null!!
    class Episode {
    lateinit var airdate: Date
    }

    View Slide

  164. Platform types in
    overrides
    How do I choose the right type when overriding Java methods?

    View Slide

  165. Platform types in overrides

    View Slide

  166. Platform types in overrides
    public interface OnClickListener {
    void onClick(Button button);
    }

    View Slide

  167. Platform types in overrides
    public interface OnClickListener {
    void onClick(Button button);
    }
    class KtListener : OnClickListener {
    override fun onClick(button: Button?): Unit {
    val name = button?.name ?: "Unknown button"
    println("Clicked ${name}")
    }
    }

    View Slide

  168. Platform types in overrides
    public interface OnClickListener {
    void onClick(Button button);
    }
    class KtListener : OnClickListener {
    override fun onClick(button: Button?): Unit {
    val name = button?.name ?: "Unknown button"
    println("Clicked ${name}")
    }
    }

    View Slide

  169. Platform types in overrides
    public interface OnClickListener {
    void onClick(Button button);
    }
    class KtListener : OnClickListener {
    override fun onClick(button: Button?): Unit {
    val name = button?.name ?: "Unknown button"
    println("Clicked ${name}")
    }
    }

    View Slide

  170. Platform types in overrides
    public interface OnClickListener {
    void onClick(Button button);
    }
    class KtListener : OnClickListener {
    override fun onClick(button: Button): Unit {
    val name = button.name
    println("Clicked ${name}")
    }
    }

    View Slide

  171. Import aliases
    What can I do about imports with conflicting names?

    View Slide

  172. Import aliases

    View Slide

  173. Import aliases
    package com.example.code
    fun indent(str: String)
    : String { ... }
    package com.example.square
    fun indent(str: String)
    : String { ... }

    View Slide

  174. Import aliases
    package com.example.code
    fun indent(str: String)
    : String { ... }
    package com.example.square
    fun indent(str: String)
    : String { ... }
    import com.example.code.indent
    indent("hello")
    com.example.square.indent("world")

    View Slide

  175. Import aliases
    package com.example.code
    fun String.indent()
    : String { ... }
    package com.example.square
    fun String.indent()
    : String { ... }

    View Slide

  176. Import aliases
    package com.example.code
    fun String.indent()
    : String { ... }
    package com.example.square
    fun String.indent()
    : String { ... }
    import com.example.code.indent
    "hello".indent()
    "world".indent()

    View Slide

  177. Import aliases
    package com.example.code
    fun String.indent()
    : String { ... }
    package com.example.square
    fun String.indent()
    : String { ... }
    import com.example.code.indent as indent4
    import com.example.square.indent as indent2
    "hello".indent4()
    "world".indent2()

    View Slide

  178. Import aliases
    import java.util.Date as UtilDate
    import java.sql.Date as SqlDate
    fun matches(date1: UtilDate, date2: SqlDate): Boolean {
    ...
    }

    View Slide

  179. Kotlin vs Java for
    Android development
    Please help I just started

    View Slide

  180. Kotlin vs Java for Android development

    View Slide

  181. Kotlin vs Java for Android development

    View Slide

  182. Recap
    • 1. Array vs IntArray
    • 2. Iterable vs Sequence
    • 3. Iteration (with indexes)
    • 4. SAM conversions
    • 5. Replacing statics
    • 6. Smart casts on mutable properties
    • 7. null!!
    • 8. Platform types in overrides
    • 9. Import aliases
    • 10. Kotlin vs Java for Android development

    View Slide

  183. References
    • Top 10 Kotlin Stack Overflow questions, article series
     https://zsmb.co/top-10-kotlin-stack-overflow-questions-1/
    • Kotlin tag on Stack Overflow
     https://stackoverflow.com/questions/tagged/kotlin

    View Slide

  184. Photo:
    Alexey Sergeev
    Questions?
    zsmb.co zsmb13
    [email protected]

    View Slide