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

Kotlin's Advanced Language Features

Kotlin's Advanced Language Features

Benoît Quenaudon

October 18, 2018
Tweet

More Decks by Benoît Quenaudon

Other Decks in Programming

Transcript

  1. Kotlin’s Advanced Language Features

  2. High Order Function's Extension

  3. fun String.blowUp() { boom() } "Nooooo".blowUp()

  4. fun buildString( builderAction: (StringBuilder) -> Unit ): String {a }b

    fun main(args: Array<String>) {c }e
  5. fun buildString( builderAction: (StringBuilder) -> Unit ): String {a val

    sb = StringBuilder() builderAction(sb) return sb.toString() }b fun main(args: Array<String>) {c }e
  6. fun buildString( builderAction: (StringBuilder) -> Unit ): String {a val

    sb = StringBuilder() builderAction(sb) return sb.toString() }b fun main(args: Array<String>) {c val s = buildString({ stringBuilder -> stringBuilder.append("Hello, ") stringBuilder.append("World!") })d }e
  7. fun buildString( builderAction: (StringBuilder) -> Unit ): String {a val

    sb = StringBuilder() builderAction(sb) return sb.toString() }b fun main(args: Array<String>) {c val s = buildString { stringBuilder -> stringBuilder.append("Hello, ") stringBuilder.append("World!") }d }e
  8. fun buildString( builderAction: (StringBuilder) -> Unit ): String {a val

    sb = StringBuilder() builderAction(sb) return sb.toString() }b fun main(args: Array<String>) {c val s = buildString { it.append("Hello, ") it.append("World!") }d }e
  9. fun buildString( builderAction: (StringBuilder) -> Unit ): String {a val

    sb = StringBuilder() builderAction(sb) return sb.toString() }b fun main(args: Array<String>) {c val s = buildString { append("Hello, ") append("World!") }d }e
  10. fun buildString( builderAction: StringBuilder.() -> Unit ): String {a val

    sb = StringBuilder() builderAction(sb) return sb.toString() }b fun main(args: Array<String>) {c val s = buildString { append("Hello, ") append("World!") }d }e
  11. fun buildString( builderAction: StringBuilder.() -> Unit ): String {a val

    sb = StringBuilder() sb.builderAction() return sb.toString() }b fun main(args: Array<String>) {c val s = buildString { append("Hello, ") append("World!") }d }e
  12. fun buildString( builderAction: StringBuilder.() -> Unit ): String {a val

    sb = StringBuilder() sb.builderAction() return sb.toString() }b fun main(args: Array<String>) {c val s = buildString { append("Hello, ") append("World!") }d }e
  13. fun buildString( builderAction: StringBuilder.() -> Unit ): String {a val

    sb = StringBuilder() sb.builderAction() return sb.toString() }b fun main(args: Array<String>) {c val s = buildString { this.append("Hello, ") append("World!") }d }e
  14. None
  15. val taco = Taco() with(taco) { println(name) println(tasty) }

  16. fun <T, R> with( receiver: T, block: T.() -> R

    ): R { return receiver.block() }
  17. When do we seal the casting?

  18. interface BinaryNumber object Zero : BinaryNumber object One : BinaryNumber

  19. interface BinaryNumber object Zero : BinaryNumber object One : BinaryNumber

    fun BinaryNumber.toInt():Int {a return when (this) {b is One -> 1 is Zero -> 0 else -> throw IllegalStateException() }c }d
  20. interface BinaryNumber object Zero : BinaryNumber object One : BinaryNumber

    fun BinaryNumber.toInt():Int {a return when (this) {b is One -> 1 is Zero -> 0 }c }d
  21. interface BinaryNumber object Zero : BinaryNumber object One : BinaryNumber

    fun BinaryNumber.toInt():Int {a return when (this) {b is One -> 1 is Zero -> 0 else -> throw IllegalStateException() }c }d
  22. interface BinaryNumber object Zero : BinaryNumber object One : BinaryNumber

    class Magic() : BinaryNumber() { fun abracadabra() { // ... } } fun BinaryNumber.toInt():Int {a return when (this) {b is One -> 1 is Zero -> 0 else -> throw IllegalStateException() }c }d
  23. interface BinaryNumber object Zero : BinaryNumber object One : BinaryNumber

    fun BinaryNumber.toInt():Int {a return when (this) {b is One -> 1 is Zero -> 0 else -> throw IllegalStateException() }c }d
  24. sealed class BinaryNumber object Zero : BinaryNumber() object One :

    BinaryNumber() fun BinaryNumber.toInt():Int {a return when (this) {b is One -> 1 is Zero -> 0 else -> throw IllegalStateException() }c }d
  25. sealed class BinaryNumber object Zero : BinaryNumber() object One :

    BinaryNumber() fun BinaryNumber.toInt():Int {a return when (this) {b is One -> 1 is Zero -> 0 }c }d
  26. sealed class BinaryNumber object Zero : BinaryNumber() object One :

    BinaryNumber() class Magic() : BinaryNumber() {z fun abracadabra() {w // ... }t }r fun BinaryNumber.toInt():Int {a return when (this) {b is One -> 1 is Zero -> 0 }c }d
  27. sealed class BinaryNumber object Zero : BinaryNumber() object One :

    BinaryNumber() class Magic() : BinaryNumber() {z fun abracadabra() {w // ... }t }r fun BinaryNumber.toInt():Int {a return when (this) {b is One -> 1 is Zero -> 0 }c }d
  28. sealed class BinaryNumber object Zero : BinaryNumber() object One :

    BinaryNumber() class Magic() : BinaryNumber() {z fun abracadabra() {w // ... }t }r fun BinaryNumber.toInt():Int {a return when (this) {b is One -> 1 is Zero -> 0 is Magic -> this.abracadabra() }c }d
  29. sealed class BinaryNumber object Zero : BinaryNumber() object One :

    BinaryNumber() class Magic() : BinaryNumber() { fun abracadabra() { // ... } } fun BinaryNumber.toInt():Int {a return when (this) {b is One -> 1 is Zero -> 0 is Magic -> this.abracadabra() }c }d
  30. None
  31. fun requireNotNull(obj: Any?) {a if (obj == null) throw IllegalArgumentException()

    }d
  32. fun requireNotNull(obj: Any?) {a if (obj == null) throw IllegalArgumentException()

    }d fun foo(s: String?) {e requireNotNull(s) s.length }f
  33. fun requireNotNull(obj: Any?) {a contract { returns() implies (obj !=

    null) }c if (obj == null) throw IllegalArgumentException() }d fun foo(s: String?) {e requireNotNull(s) s.length }f
  34. None
  35. Error is Ever the Sequence of Haste

  36. people // List<People>

  37. people // List<People> .map(People::name) .filter { it.startsWith("J") }

  38. people // List<People> .map(People::name) // List<People> .filter { it.startsWith("J") }

    // List<People>
  39. people // List<People> .asSequence() .map(People::name) .filter { it.startsWith("J") }

  40. people // List<People> .asSequence() // Sequence<People> .map(People::name) // Sequence<String> .filter

    { it.startsWith("J") } // Sequence<String>
  41. people // List<People> .asSequence() // Sequence<People> .map(People::name) // Sequence<String> .filter

    { it.startsWith("J") } // Sequence<String> .toList() // List<People>
  42. people .map(People::name) .find { it.startsWith("J") }

  43. people .map(People::name) .find { it.startsWith("J") } And Car Jes Wil

    Pir A C J W P A C J
  44. people.asSequence() .map(People::name) .find { it.startsWith("J") } And Car Jes Wil

    Pir A C J A C J
  45. None
  46. Generics at runtime

  47. fun sumUp(items: Collection<*>) {a if (items is List<Int>) {d println(ints.sum())

    }b }c val strings: List<String> = listOf("a", "b") sumUp(strings)
  48. fun sumUp(items: Collection<*>) {a if (items is List<Int>) {d println(ints.sum())

    }b }c val strings: List<String> = listOf("a", "b") sumUp(strings)
  49. fun sumUp(items: Collection<*>) {a val ints = items as? List<Int>

    ?: return println("We got a list of ints") println(ints.sum()) }c val strings: List<String> = listOf("a", "b") sumUp(strings)
  50. fun sumUp(items: Collection<*>) {a val ints = items as? List<Int>

    ?: return println("We got a list of ints") println(ints.sum()) }c val strings: List<String> = listOf("a", "b") sumUp(strings) ----- We got a list of ints Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number
  51. fun sumUp(items: Collection<*>) {a val ints = items as? List<Int>

    ?: return println("We got a list of ints") println(ints.sum()) }c val strings: List<String> = listOf("a", "b") sumUp(strings)
  52. fun sumUp(items: Collection<Int>) {a val ints = items as? List<Int>

    ?: return println("We got a list of ints") println(ints.sum()) }c val strings: List<String> = listOf("a", "b") sumUp(strings)
  53. None
  54. fun <T> Iterable<*>.filterIsInstance(): List<T> {a val destination = mutableListOf<T>() for

    (element in this) {c if (element is T) {d destination.add(element) }p }e return destination }f
  55. fun <T> Iterable<*>.filterIsInstance(): List<T> {a val destination = mutableListOf<T>() for

    (element in this) {c if (element is T) {d destination.add(element) }p }e return destination }f listOf("a", 1, 0x0, 2L, 'u') .filterIsInstance<String>()
  56. fun <T> Iterable<*>.filterIsInstance(): List<T> {a val destination = mutableListOf<T>() for

    (element in this) {c if (element is T) {d destination.add(element) }p }e return destination }f listOf("a", 1, 0x0, 2L, 'u') .filterIsInstance<Int>()
  57. fun <T> Iterable<*>.filterIsInstance(): List<T> {a val destination = mutableListOf<T>() for

    (element in this) {c if (element is T) {d destination.add(element) }p }e return destination }f listOf("a", 1, 0x0, 2L, 'u') .filterIsInstance<Char>()
  58. fun <T> Iterable<*>.filterIsInstance(): List<T> {a val destination = mutableListOf<T>() for

    (element in this) {c if (element is T) {d destination.add(element) }p }e return destination }f
  59. None
  60. fun <T> Iterable<*>.filterIsInstance(): List<T> {a val destination = mutableListOf<T>() for

    (element in this) {c if (element is T) {d destination.add(element) }p }e return destination }f
  61. inline fun <T> Iterable<*>.filterIsInstance(): List<T> {a val destination = mutableListOf<T>()

    for (element in this) {c if (element is T) {d destination.add(element) }p }e return destination }f
  62. inline fun <reified T> Iterable<*>.filterIsInstance(): List val destination = mutableListOf<T>()

    for (element in this) {c if (element is T) {d destination.add(element) }p }e return destination }f
  63. inline fun <reified T> Iterable<*>.filterIsInstance(): List val destination = mutableListOf<T>()

    for (element in this) {c if (element is T) {d destination.add(element) }p }e return destination }f
  64. inline fun <reified T> Iterable<*>.filterIsInstance(): List val destination = mutableListOf<T>()

    for (element in this) {c if (element is T) {d destination.add(element) }p }e return destination }f listOf("a", 1, 0x0, 2L, 'u') .filterIsInstance<String>()
  65. None
  66. val moshi = Moshi.Builder().build() moshi.adapter(String::class.java) // JsonAdapter<String>

  67. val moshi = Moshi.Builder().build() moshi.adapter(String::class.java)

  68. val moshi = Moshi.Builder().build() moshi.adapter<String>()

  69. inline fun <reified T> Moshi.adapter(): JsonAdapter<T> {a return this.adapter(T::class.java) }b

    val moshi = Moshi.Builder().build() moshi.adapter<String>()
  70. None
  71. If you really want to grow as a Klass, you've

    got to learn to delegate
  72. class canTbeextended open class canbeextended

  73. class CountingSet<T>( val innerSet: MutableCollection<T> = HashSet() ) : MutableCollection<T>

    {abcdefgh }t
  74. class CountingSet<T>( val innerSet: MutableCollection<T> = HashSet() ) : MutableCollection<T>

    {abcdefgh var objectsAdded = 0 }t
  75. class CountingSet<T>( val innerSet: MutableCollection<T> = HashSet() ) : MutableCollection<T>

    {abcdefgh var objectsAdded = 0 override fun add(element: T): Boolean {w objectsAdded++ return innerSet.add(element) }p override fun addAll(c: Collection<T>): Boolean {o objectsAdded += c.size return innerSet.addAll(c) }k }t
  76. class CountingSet<T>( val innerSet: MutableCollection<T> = HashSet() ) : MutableCollection<T>

    {abcdefgh var objectsAdded = 0 override fun add(element: T): Boolean {w objectsAdded++ return innerSet.add(element) }p override fun addAll(c: Collection<T>): Boolean {o objectsAdded += c.size return innerSet.addAll(c) }k }t
  77. class CountingSet<T>( val innerSet: MutableCollection<T> = HashSet() ) : MutableCollection<T>

    {abcdefgh var objectsAdded = 0 override fun add(element: T): Boolean {w objectsAdded++ return innerSet.add(element) }p override fun addAll(c: Collection<T>): Boolean {o objectsAdded += c.size return innerSet.addAll(c) }k override val size: Int get() = innerSet.size override fun contains(element: T): Boolean { return innerSet.contains(element) } override fun containsAll(elements: Collection<T>): Boolean { return innerSet.containsAll(elements) } override fun isEmpty(): Boolean { return innerSet.isEmpty() } override fun clear() { innerSet.clear() } override fun iterator(): MutableIterator<T> { return innerSet.iterator() } override fun remove(element: T): Boolean { return innerSet.remove(element) } override fun removeAll(elements: Collection<T>): Boolean { return innerSet.removeAll(elements) } override fun retainAll(elements: Collection<T>): Boolean { return innerSet.retainAll(elements) } }t
  78. class CountingSet<T>( val innerSet: MutableCollection<T> = HashSet() ) : MutableCollection<T>

    {abcdefgh var objectsAdded = 0 override fun add(element: T): Boolean {w objectsAdded++ return innerSet.add(element) }p override fun addAll(c: Collection<T>): Boolean {o objectsAdded += c.size return innerSet.addAll(c) }k }t
  79. class CountingSet<T>( val innerSet: MutableCollection<T> = HashSet() ) : MutableCollection<T>

    by innerSet {abcdefgh var objectsAdded = 0 override fun add(element: T): Boolean {w objectsAdded++ return innerSet.add(element) }p override fun addAll(c: Collection<T>): Boolean {o objectsAdded += c.size return innerSet.addAll(c) }k }t
  80. class CountingSet<T>( val innerSet: MutableCollection<T> = HashSet() ) : MutableCollection<T>

    by innerSet {abcdefgh var objectsAdded = 0 override fun add(element: T): Boolean {w objectsAdded++ return innerSet.add(element) }p override fun addAll(c: Collection<T>): Boolean {o objectsAdded += c.size return innerSet.addAll(c) }k }t
  81. None
  82. class Foo { val data: Int by lazy { computeStuff()

    } } • lazy • observable • vetoable • notNull
  83. The Secret of Success of to Triple Your Quotes

  84. """(.+)"(.+)"(.+)""".toRegex() new Regex("(.+)\"(.+)\"(.+)") "C:\\Users\\yole\\kotlin-book" """C:\Users\yole\kotlin-book""" """${'$'}99.9""" "\$99.9" "$99.9" Java Kotlin

  85. assertThat(toString(taco)).isEqualTo("" + "package com.squareup.tacos\n" + "\n" + "import kotlin.String\n" +

    "\n" + "class Taco {\n" + " final override fun toString(): String = \"taco\"\n" + "}\n" + "")c
  86. assertThat(toString(taco)).isEqualTo(""" package com.squareup.tacos import kotlin.String class Taco { final override

    fun toString(): String = "taco" }z """)c
  87. assertThat(toString(taco)).isEqualTo(""" package com.squareup.tacos import kotlin.String class Taco { final override

    fun toString(): String = "taco" }z """)c
  88. assertThat(toString(taco)).isEqualTo(""" |package com.squareup.tacos | |import kotlin.String | |class Taco {

    | final override fun toString(): String = "taco" |}z |""")c
  89. assertThat(toString(taco)).isEqualTo(""" |package com.squareup.tacos | |import kotlin.String | |class Taco {

    | final override fun toString(): String = "taco" |} |""".trimMargin())c
  90. None
  91. And if you want these kind of dreams it's Deprecation

  92. class SomeList {a fun remove(index: Int) {b }c }f

  93. class SomeList {a fun remove(index: Int) {b }c fun removeAt(index:

    Int) {d }e }f
  94. class SomeList {a @Deprecated("Use removeAt(index) instead.")h fun remove(index: Int) {b

    }c fun removeAt(index: Int) {d }e }f
  95. class SomeList {a @Deprecated("Use removeAt(index) instead.", ReplaceWith("removeAt(index)"))h fun remove(index: Int)

    {b }c fun removeAt(index: Int) {d }e }f
  96. class SomeList {a @Deprecated("Use removeAt(index) instead.", ReplaceWith("removeAt(index)"))h fun remove(index: Int)

    {b }c fun removeAt(index: Int) {d }e }f
  97. Live Demo

  98. None