Kotlin's Advanced Language Features

Kotlin's Advanced Language Features

05162bc961c3654218bf1839974a4f35?s=128

Benoît Quenaudon

October 18, 2018
Tweet

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