Kotlin Fest 2019: Kotlin型実践入門

2793f1fe246c9299c2416062d22bfb99?s=47 Sato Shun
August 24, 2019

Kotlin Fest 2019: Kotlin型実践入門

KotlinではJavaにはない様々な型に関する機能が追加されたので、それらの解説

- Smart Casts
- Any、Unit、Nothing
- ジェネリクス
- Sealed class
- 関数型

2793f1fe246c9299c2416062d22bfb99?s=128

Sato Shun

August 24, 2019
Tweet

Transcript

  1. Kotlin Fest 2019 ࠤ౻ ൏ / Sato Shun Twitter: @stsn_jp

    GitHub: satoshun Kotlinܕ࣮ફೖ໳
  2. ֓ཁ • KotlinͰ͸Javaʹ͸ͳ͍༷ʑͳܕʹؔ͢Δػೳ͕௥Ճ͞Εͨ ͷͰɺͦΕΒͷղઆ • ॳֶऀ޲͚ͷ಺༰ʹͳ͓ͬͯΓ·͢

  3. ໨࣍ • Smart Casts • AnyɺUnitɺNothing • δΣωϦΫε • Sealed

    class • ؔ਺ܕ
  4. •Smart Casts • AnyɺUnitɺNothing • δΣωϦΫε • Sealed class •

    ؔ਺ܕ
  5. Smart Casts • ifࣜɺwhenࣜɺisɺasͳͲͷ࣮ߦޙʹɺ໌ࣔతʹܕΩϟετ ͠ͳͯ͘΋ɺܕΛਪ࿦ͯ͘͠ΕΔ • flow-sensitive typing (flow typing)ͱݺ͹ΕΔܕγεςϜ

  6. Smart Casts • ifࣜɺwhenࣜɺisɺasͳͲͷ࣮ߦޙʹɺ໌ࣔతʹܕΩϟετ ͠ͳͯ͘΋ɺܕΛਪ࿦ͯ͘͠ΕΔ • flow-sensitive typing (flow typing)ͱݺ͹ΕΔܕγεςϜ

    • ৑௕ͳܕΩϟετΛܰݮ͢Δ • ಈతܕ෇͚ݴޠͷμοΫλΠϐϯάͷΑ͏ͳॻ͖৺஍ • https://en.wikipedia.org/wiki/Flow-sensitive_typing
  7. if (obj is String) { a print((obj as String).length) }

    a if (obj !is String) return print((obj as String).length) when (obj) { aa is Int -> print((obj as Int) + 1) is String -> print((obj as String).length + 1) is IntArray -> print((obj as IntArray).sum() + 1) } a
  8. if (obj is String) { a print(obj.length) } a if

    (obj !is String) return print((obj as String).length) when (obj) { aa is Int -> print((obj as Int) + 1) is String -> print((obj as String).length + 1) is IntArray -> print((obj as IntArray).sum() + 1) } a
  9. if (obj is String) { a print(obj.length) } a if

    (obj !is String) return print(obj.length) when (obj) { aa is Int -> print((obj as Int) + 1) is String -> print((obj as String).length + 1) is IntArray -> print((obj as IntArray).sum() + 1) } a
  10. if (obj is String) { a print(obj.length) } a if

    (obj !is String) return print(obj.length) when (obj) { a is Int -> print(obj + 1) is String -> print(obj.length + 1) is IntArray -> print(obj.sum() + 1) } a
  11. if (hoge() && obj is Int) { a (obj as

    Int).toLong() } a if (obj is String && obj is Int) { a (obj as String).length (obj as Int).toLong() } a
  12. if (hoge() && obj is Int) { a obj.toLong() }

    a if (obj is String && obj is Int) { a (obj as String).length (obj as Int).toLong() } a
  13. if (hoge() && obj is Int) { a obj.toLong() }

    a if (obj is String && obj is Int) { a obj.length obj.toLong() } a
  14. class Hoge { a private var obj: Any = "a"

    fun test() { a if (obj is String) { a print((obj as String).length) } a } a } a
  15. class Hoge { a private var obj: Any = "a"

    fun test() { a if (obj is String) { a print(obj.length) } a } a } a
  16. class Hoge { a private var obj: Any = "a"

    fun test() { a if (obj is String) { a print(obj.length) } a } a } a ❌
  17. class Hoge { a private var obj: Any = "a"

    fun test() { a val obj = obj if (obj is String) { a print(obj.length) } a } a } a
  18. class Hoge { a private var obj: Any = "a"

    fun test() { a obj.let { a if (it is String) { a print(it.length) } a } a } a } a
  19. val strs: List<String>? = … a if (!strs.isNullOrEmpty()) { a

    println(strs!!.size) } a
  20. val strs: List<String>? = … a if (!strs.isNullOrEmpty()) { a

    println(strs.size) } a
  21. Contracts • Smart CastsΛ֦ு͢Δػೳ • ؔ਺ݺͼग़͠ͷ݁ՌΛ΋ͱʹɺSmart Casts͢Δ͜ͱ͕ग़དྷ Δ

  22. public inline fun <T> Collection<T>?.isNullOrEmpty(): Boolean { a contract {

    a returns(false) implies (this@isNullOrEmpty != null) } a return this == null || this.isEmpty() } a
  23. public inline fun <T> Collection<T>?.isNullOrEmpty(): Boolean { a contract {

    a returns(false) implies (this@isNullOrEmpty != null) } a return this == null || this.isEmpty() } a
  24. public inline fun <T> Collection<T>?.isNullOrEmpty(): Boolean { a contract {

    a returns(false) implies (this@isNullOrEmpty != null) } a return this == null || this.isEmpty() } a
  25. public inline fun <T> Collection<T>?.isNullOrEmpty(): Boolean { a contract {

    a returns(false) implies (this@isNullOrEmpty != null) } a return this == null || this.isEmpty() } a
  26. val strs: List<String>? = … a if (!strs.isNullOrEmpty()) { a

    println(strs!!.size) } a
  27. val strs: List<String>? = … a if (!strs.isNullOrEmpty()) { a

    println(strs.size) } a
  28. fun assertTrue(actual: Boolean, message: String? = null) { a contract

    { returns() implies actual } a return asserter.assertTrue(message ?: "Expected value to be true.", actual) } a
  29. fun assertTrue(actual: Boolean, message: String? = null) { a contract

    { returns() implies actual } a return asserter.assertTrue(message ?: "Expected value to be true.", actual) } a
  30. fun assertTrue(actual: Boolean, message: String? = null) { a contract

    { returns() implies actual } a return asserter.assertTrue(message ?: "Expected value to be true.", actual) } a assertTrue(obj != null) print(obj!!.length)
  31. fun assertTrue(actual: Boolean, message: String? = null) { a contract

    { returns() implies actual } a return asserter.assertTrue(message ?: "Expected value to be true.", actual) } a assertTrue(obj != null) print(obj.length)
  32. fun assertFalse(actual: Boolean, message: String? = null) { contract {

    returns() implies (!actual) } return asserter.assertTrue(message ?: "Expected value to be false.", !actual) } assertFalse(obj == null) print(obj.length)
  33. fun assertFalse(actual: Boolean, message: String? = null) { contract {

    returns() implies (!actual) } return asserter.assertTrue(message ?: "Expected value to be false.", !actual) } assertFalse(obj == null) print(obj.length)
  34. public inline fun <R> run(block: () -> R): R {

    a contract { a callsInPlace(block, InvocationKind.EXACTLY_ONCE) } a return block() } a
  35. public inline fun <R> run(block: () -> R): R {

    a contract { a callsInPlace(block, InvocationKind.EXACTLY_ONCE) } a return block() } a
  36. public inline fun <R> run(block: () -> R): R {

    a contract { a callsInPlace(block, InvocationKind.EXACTLY_ONCE) } a return block() } a var s: String? = null a run { a s = "" a } a println(s!!) a
  37. public inline fun <R> run(block: () -> R): R {

    a contract { a callsInPlace(block, InvocationKind.EXACTLY_ONCE) } a return block() } a val s: String a run { a s = "" a } a println(s) a
  38. fun checkObj(obj: Any?): Boolean { a return obj != null

    } a if (checkObj(obj)) { a obj!!.javaClass } a
  39. fun checkObj(obj: Any?): Boolean { a contract { a returns(true)

    implies (obj != null) } a return obj != null } a if (checkObj(obj)) { a obj!!.javaClass } a
  40. fun checkObj(obj: Any?): Boolean { a contract { a returns(true)

    implies (obj != null) } a return obj != null } a if (checkObj(obj)) { a obj!!.javaClass } a
  41. fun checkObj(obj: Any?): Boolean { a contract { a returns(true)

    implies (obj != null) } a return obj != null } a if (checkObj(obj)) { a obj!!.javaClass } a
  42. fun checkObj(obj: Any?): Boolean { a contract { a returns(true)

    implies (obj != null) } a return obj != null } a if (checkObj(obj)) { a obj.javaClass } a
  43. @UseExperimental(ExperimentalContracts::class) fun checkObj(obj: Any?): Boolean { a contract { a

    returns(true) implies (obj != null) } a return obj != null } a if (checkObj(obj)) { a obj.javaClass } a
  44. • Smart Casts •AnyɺUnitɺNothing • δΣωϦΫε • Sealed class •

    ؔ਺ܕ
  45. Anyܕ • ͢΂ͯͷKotlinͷΫϥεͷεʔύʔΫϥε • ϧʔτΫϥε • Javaͷ৔߹ɺjava.lang.Object͕ϧʔτΫϥε

  46. Anyܕ • JavaͷObjectͱҧ͏఺͸Ͳ͔͜ʁ • waitɺnotifyϝιου͕࢖͑ͳ͍ • ໌ࣔతʹjava.lang.ObjectܕʹΩϟετ͢Ε͹ݺͼग़ͤΔ • getClassϝιου͕֦ுؔ਺ʹ •

    public inline val <T : Any> T.javaClass: Class<T> • cloneɺfinalizeϝιου
  47. val s = "" s.notify()

  48. val s = "" (s as Object).notify()

  49. Unitܕ • JavaͰ͍͏ͱ͜ΖͷvoidΛදݱ͢ΔΫϥε • ฦΓ஋͕ۭͰ͋Δ͜ͱΛද͢

  50. fun empty() { a } a empty()

  51. fun empty(): Unit { a } a empty()

  52. fun empty(): Unit { a } a val e =

    empty() println(e)
  53. fun empty() { a } a val e = empty()

    println(e)
  54. Nothingܕ • ͢΂ͯͷKotlinͷΫϥεͷαϒΫϥε • ஋͕ଘࡏ͠ͳ͍͜ͱΛࣔ͢ • ਖ਼ৗऴྃ͢Δ͜ͱ͕ͳ͍ؔ਺ͷฦΓ஋ʹ࢖͑Δ

  55. fun getName(): String { a return "name" } a fun

    fail() { a throw RuntimeException() } a
  56. fun getName(): String { a return "name" } a fun

    fail() { a throw RuntimeException() } a val name = if (isFriend()) { a getName() } a else { a fail() } a
  57. fun getName(): String { a return "name" } a fun

    fail() { a throw RuntimeException() } a val name: Any = if (isFriend()) { a getName() } a else { a fail() } a
  58. fun getName(): String { a return "name" } a fun

    fail() { a throw RuntimeException() } a val name: Any = if (isFriend()) { a getName() } a else { a fail() } a
  59. fun getName(): String { a return "name" } a fun

    fail() { a throw RuntimeException() } a val name: Any = if (isFriend()) { a getName() } a else { a fail() } a println((name as String).length)
  60. fun getName(): String { a return "name" } a fun

    fail(): Nothing { a throw RuntimeException() } a val name: Any = if (isFriend()) { a getName() } a else { a fail() } a println((name as String).length)
  61. fun getName(): String { a return "name" } a fun

    fail(): Nothing { a throw RuntimeException() } a val name: Any = if (isFriend()) { a getName() } a else { a fail() } a println((name as String).length)
  62. fun getName(): String { a return "name" } a fun

    fail(): Nothing { a throw RuntimeException() } a val name: Any = if (isFriend()) { a getName() } a else { a fail() } a println((name as String).length)
  63. fun getName(): String { a return "name" } a fun

    fail(): Nothing { a throw RuntimeException() } a val name: String = if (isFriend()) { a getName() } a else { a fail() } a println((name as String).length)
  64. fun getName(): String { a return "name" } a fun

    fail(): Nothing { a throw RuntimeException() } a val name: String = if (isFriend()) { a getName() } a else { a fail() } a println(name.length)
  65. fun getName(): String { a return "name" } a fun

    fail(): Nothing { a throw RuntimeException() } a val name = if (isFriend()) { a getName() } a else { a fail() } a println(name.length)
  66. fun test(any: Any): String { a when (any) { a

    is Int -> return "int" else -> fail() } a return "error" } a
  67. fun test(any: Any): String { a when (any) { a

    is Int -> return "int" else -> fail() } a return "error" } a NothingܕͳͷͰɺ͜ͷݺͼग़͠͸ਖ਼ৗʹऴྃ͠ͳ͍ ͜ͷelse͸ඞࣦͣഊ͢Δ
  68. fun test(any: Any): String { a when (any) { a

    is Int -> return "int" else -> fail() } a } a
  69. // ඪ४ؔ਺ public inline fun TODO(): Nothing = throw NotImplementedError()

    // KotlinTest fun fail(msg: String): Nothing = throw Failures.failure(msg)
  70. // Kotlin/kotlinx.collections.immutable internal companion object { internal val EMPTY =

    TrieNode<Nothing>(0, emptyArray()) } // airbnb/MvRx object Uninitialized : Async<Nothing>(complete = false, shouldLoad = true), Incomplete
  71. fun test2() { a while (true) { a println(".") }

    a } a
  72. fun test2(): Nothing { a while (true) { a println(".")

    } a } a
  73. Nothing?ܕ • Nothing?ܕ΋ଘࡏ͢Δ • Nothing͸஋ͱͯ͠ଘࡏ͠ͳ͍ͷͰɺnullͷΈΛڐՄ͢Δ

  74. // kotlintest/kotlintest interface Show<in A> { a fun supports(a: Any?):

    Boolean fun show(a: A): String } a object NullShow : Show<Nothing?> { a override fun supports(a: Any?): Boolean = a == null override fun show(a: Nothing?): String = "<null>" } a
  75. • Smart Casts • AnyɺUnitɺNothing •δΣωϦΫε • Sealed class •

    ؔ਺ܕ
  76. δΣωϦΫε • ෼ࢄΞϊςʔγϣϯʢvariance annotationʣ • outɺinम০ࢠ • એݴଆมੑ: declaration-site variance

    • where • reified • ֦ுؔ਺ + δΣωϦΫε
  77. ෼ࢄΞϊςʔγϣϯ • out - ڞม: covariance • in - ൓ม:

    contravariance • ࢦఆͳ͠: ෆม: invariance
  78. ڞมɺ൓มɺෆม • Number <|- Intͷܧঝؔ܎͕͋Δ

  79. ڞมɺ൓มɺෆม • Number <|- Intͷܧঝؔ܎͕͋Δ • A<Number> <|- A<Int>ͷ৔߹ɺA͸ڞมͰ͋Δ

  80. ڞมɺ൓มɺෆม • Number <|- Intͷܧঝؔ܎͕͋Δ • A<Number> <|- A<Int>ͷ৔߹ɺA͸ڞมͰ͋Δ

  81. ڞมɺ൓มɺෆม • Number <|- Intͷܧঝؔ܎͕͋Δ • A<Number> <|- A<Int>ͷ৔߹ɺA͸ڞมͰ͋Δ •

    A<Number> -|> A<Int>ͷ৔߹ɺA͸൓มͰ͋Δ
  82. ڞมɺ൓มɺෆม • Number <|- Intͷܧঝؔ܎͕͋Δ • A<Number> <|- A<Int>ͷ৔߹ɺA͸ڞมͰ͋Δ •

    A<Number> -|> A<Int>ͷ৔߹ɺA͸൓มͰ͋Δ
  83. ڞมɺ൓มɺෆม • Number <|- Intͷܧঝؔ܎͕͋Δ • A<Number> <|- A<Int>ͷ৔߹ɺA͸ڞมͰ͋Δ •

    A<Number> -|> A<Int>ͷ৔߹ɺA͸൓มͰ͋Δ • A<Number>ɺ A<Int>͕ؔ܎ͳ͍৔߹ɺA͸ෆมͰ͋Δ
  84. ڞมɺ൓มɺෆม • Number <|- Intͷܧঝؔ܎͕͋Δ • A<Number> <|- A<Int>ͷ৔߹ɺA͸ڞมͰ͋Δ •

    A<Number> -|> A<Int>ͷ৔߹ɺA͸൓มͰ͋Δ • A<Number>ɺ A<Int>͕ؔ܎ͳ͍৔߹ɺA͸ෆมͰ͋Δ
  85. // ڞม val a: A<Int> = A<Int>() a val b:

    A<Number> = a
  86. // ڞม val a: A<Int> = A<Int>() a val b:

    A<Number> = a // ൓ม val a: A<Number> = A<Number>() a val b: A<Int> = a
  87. // ڞม val a: A<Int> = A<Int>() a val b:

    A<Number> = a // ൓ม val a: A<Number> = A<Number>() a val b: A<Int> = a // ෆม val a: A<Int> = A<Int>() a
  88. interface Mapper<T> { a fun map(s: String): T } a

    class IntMapper : Mapper<Int> { a override fun map(s: String): Int = s.toInt() } a
  89. interface Mapper<T> { a fun map(s: String): T } a

    class IntMapper : Mapper<Int> { a override fun map(s: String): Int = s.toInt() } a fun hoge(mapper: Mapper<Number>) { a mapper.map("10") } a
  90. interface Mapper<T> { a fun map(s: String): T } a

    class IntMapper : Mapper<Int> { a override fun map(s: String): Int = s.toInt() } a fun hoge(mapper: Mapper<Number>) { a mapper.map("10") } a val mapper = IntMapper() hoge(mapper)
  91. interface Mapper<T> { a fun map(s: String): T } a

    class IntMapper : Mapper<Int> { a override fun map(s: String): Int = s.toInt() } a fun hoge(mapper: Mapper<Number>) { a mapper.map("10") } a val mapper = IntMapper() hoge(mapper) ❌
  92. interface Mapper<T> { a fun map(s: String): T } a

    class IntMapper : Mapper<Int> { a override fun map(s: String): Int = s.toInt() } a fun hoge(mapper: Mapper<Number>) { a mapper.map("10") } a val mapper = IntMapper() hoge(mapper) ❌
  93. interface Mapper<out T> { a fun map(s: String): T }

    a class IntMapper : Mapper<Int> { a override fun map(s: String): Int = s.toInt() } a fun hoge(mapper: Mapper<Number>) { a mapper.map("10") } a val mapper = IntMapper() hoge(mapper) ❌
  94. interface Mapper<out T> { a fun map(s: String): T }

    a class IntMapper : Mapper<Int> { a override fun map(s: String): Int = s.toInt() } a fun hoge(mapper: Mapper<Number>) { a mapper.map("10") } a val mapper = IntMapper() hoge(mapper) ❌
  95. interface Mapper<out T> { a fun map(s: String): T }

    a class IntMapper : Mapper<Int> { a override fun map(s: String): Int = s.toInt() } a fun hoge(mapper: Mapper<Number>) { a mapper.map("10") } a val mapper = IntMapper() hoge(mapper)
  96. ListͱMutableList public interface List<out E> : Collection<E> public interface MutableList<E>

    : List<E>, …
  97. ListͱMutableList public interface List<out E> : Collection<E> public interface MutableList<E>

    : List<E>, … • List͸outम০ࢠ͕෇͍͍ͯΔͷͰɺڞม • MutableList͸Կ΋෇͍͍ͯͳ͍ͷͰɺෆม
  98. val strs: List<String> = listOf("a", “b")

  99. val strs: List<String> = listOf("a", “b") val anys: List<Any> =

    strs
  100. val strs: List<String> = listOf("a", “b") val anys: List<Any> =

    strs val a: Any = anys[0]
  101. val strs: List<String> = listOf("a", “b") val anys: List<Any> =

    strs val a: Any = anys[0] val a2: Any? = anys2.getOrNull(1)
  102. val strs: List<String> = listOf("a", “b") val anys: List<Any> =

    strs val a: Any = anys[0] val a2: Any? = anys2.getOrNull(1)
  103. val strs: MutableList<String> = mutableListOf("a", "b")

  104. val strs: MutableList<String> = mutableListOf("a", "b") val anys: MutableList<Any> =

    strs
  105. val strs: MutableList<String> = mutableListOf("a", "b") val anys: MutableList<Any> =

    strs anys.add(10)
  106. val strs: MutableList<String> = mutableListOf("a", "b") val anys: MutableList<Any> =

    strs anys.add(10)
  107. val strs: MutableList<String> = mutableListOf("a", "b") val anys: MutableList<Any> =

    strs anys.add(10) val str: String = strs.last()
  108. val strs: MutableList<String> = mutableListOf("a", "b") val anys: MutableList<Any> =

    strs anys.add(10) val str: String = strs.last() ❌
  109. val strs: MutableList<String> = mutableListOf("a", "b") val anys: MutableList<Any> =

    strs anys.add(10) val str: String = strs.last()
  110. PECS • Producer Extends Consumer Super • Producer͸readͷੑ࣭Λ࣋ͭ • Consumer͸writeͷੑ࣭Λ࣋ͭ

    • List͸Producerͷੑ࣭ͷΈΛ࣋ͭͷͰɺExtends = out ڞมʹ ग़དྷΔ • MutableList͸ProducerͱConsumerͷੑ࣭Λ࣋ͭͷͰɺෆม
  111. 2ͭҎ্ͷ্քΛ࣋ͭܕม਺ • 1ͭͷ্քʢupper boundʣΛ࣋ͭͱ͖͸ɺׅހ಺ʹॻ͚͹ྑ ͍

  112. 2ͭҎ্ͷ্քΛ࣋ͭܕม਺ • 1ͭͷ্քʢupper boundʣΛ࣋ͭͱ͖͸ɺׅހ಺ʹॻ͚͹ྑ ͍ • fun <T : CharSequence>

    hoge(t: T) {…}
  113. 2ͭҎ্ͷ্քΛ࣋ͭܕม਺ • 1ͭͷ্քʢupper boundʣΛ࣋ͭͱ͖͸ɺׅހ಺ʹॻ͚͹ྑ ͍ • fun <T : CharSequence>

    hoge(t: T) {…} • 2ͭҎ্ͷ্քΛ࣋ͭ৔߹͸Ͳ͏͢Ε͹Α͍͔ʁ • ྫ͑͹ɺActivity͔ͭOnClickListenerΛ࣋ͭܕΛड͚ೖΕΔܕ ม਺Λఆ͍ٛͨ͠
  114. class OnClickActivity() : Activity(), OnClickListener

  115. class OnClickActivity() : Activity(), OnClickListener fun setClick(activity: OnClickActivity) { a

    } a
  116. class OnClickActivity() : Activity(), OnClickListener fun setClick(activity: OnClickActivity) { a

    } a val activity = OnClickActivity() setClick(activity)
  117. class OnClickActivity() : Activity(), OnClickListener fun setClick(activity: OnClickActivity) { a

    } a val activity = OnClickActivity() setClick(activity) class OnClickActivity2() : Activity(), OnClickListener
  118. class OnClickActivity() : Activity(), OnClickListener fun setClick(activity: OnClickActivity) { a

    } a val activity = OnClickActivity() setClick(activity) class OnClickActivity2() : Activity(), OnClickListener val activity2 = OnClickActivity2() setClick(activity2)
  119. class OnClickActivity() : Activity(), OnClickListener fun setClick(activity: OnClickActivity) { a

    } a val activity = OnClickActivity() setClick(activity) class OnClickActivity2() : Activity(), OnClickListener val activity2 = OnClickActivity2() setClick(activity2) ❌
  120. fun setClick(activity: OnClickActivity) { a } a

  121. fun <T> setClick(activity: T)

  122. fun <T> setClick(activity: T) where T : Activity, T :

    OnClickListener { a } a
  123. fun <T> setClick(activity: T) where T : Activity, T :

    OnClickListener { a } a val activity = OnClickActivity() setClick(activity)
  124. fun <T> setClick(activity: T) where T : Activity, T :

    OnClickListener { } val activity = OnClickActivity() setClick(activity) val activity2 = OnClickActivity2() setClick(activity2)
  125. internal abstract class NIOSocketImpl<out S>( override val channel: S, val

    selector: SelectorManager, val pool: ObjectPool<ByteBuffer>? ) : ReadWriteSocket, SelectableBase(channel), CoroutineScope where S : java.nio.channels.ByteChannel, S : java.nio.channels.SelectableChannel Ktor
  126. internal abstract class NIOSocketImpl<out S>( override val channel: S, val

    selector: SelectorManager, val pool: ObjectPool<ByteBuffer>? ) : ReadWriteSocket, SelectableBase(channel), CoroutineScope where S : java.nio.channels.ByteChannel, S : java.nio.channels.SelectableChannel Ktor
  127. internal abstract class NIOSocketImpl<out S>( override val channel: S, val

    selector: SelectorManager, val pool: ObjectPool<ByteBuffer>? ) : ReadWriteSocket, SelectableBase(channel), CoroutineScope where S : java.nio.channels.ByteChannel, S : java.nio.channels.SelectableChannel internal class DatagramSocketImpl(override val channel: DatagramChannel, selector: SelectorManager) : BoundDatagramSocket, ConnectedDatagramSocket, NIOSocketImpl<DatagramChannel>(channel, selector, DefaultDatagramByteBufferPool) Ktor
  128. internal abstract class NIOSocketImpl<out S>( override val channel: S, val

    selector: SelectorManager, val pool: ObjectPool<ByteBuffer>? ) : ReadWriteSocket, SelectableBase(channel), CoroutineScope where S : java.nio.channels.ByteChannel, S : java.nio.channels.SelectableChannel internal class DatagramSocketImpl(override val channel: DatagramChannel, selector: SelectorManager) : BoundDatagramSocket, ConnectedDatagramSocket, NIOSocketImpl<DatagramChannel>(channel, selector, DefaultDatagramByteBufferPool) internal class SocketImpl<out S : SocketChannel>( override val channel: S, private val socket: java.net.Socket, selector: SelectorManager ) : NIOSocketImpl<S>(channel, selector, pool = null), Socket Ktor
  129. reified • ؔ਺಺͔Βܕม਺ʹΞΫηεग़དྷΔ • JavaͰ͸ܕม਺ʹϥϯλΠϜ࣌ʹΞΫηεͰ͖ͳ͍ • Type Erasureͱݺ͹ΕΔݴޠ࢓༷ͷͨΊɺίϯύΠϧޙʹܕม਺͕ ࡟আ͞ΕΔͨΊ

  130. inline fun <reified T> hoge(obj: Any) { a println(T::class.java) a

    if (obj is T) { a println("obj is T") a } a } a
  131. inline fun <reified T> hoge(obj: Any) { a println(T::class.java) a

    if (obj is T) { a println("obj is T") a } a } a
  132. inline fun <reified T> hoge(obj: Any) { a println(T::class.java) a

    if (obj is T) { a println("obj is T") a } a } a
  133. ֦ுؔ਺ + δΣωϦΫε • Kotlinͷ֦ுؔ਺ͱδΣωϦΫεΛ૊Έ߹ΘͤΔͱΑΓॊೈʹ ܕม਺Λίϯτϩʔϧ͢Δ͜ͱ͕ग़དྷΔ

  134. class A<T>(val value: T) { a fun isNull(): Boolean {

    a return value != null } a } a
  135. class A<T>(val value: T) { a fun isNull(): Boolean {

    a return value != null } a } a val a1: A<Int?> = A(null) a a1.isNull() a
  136. class A<T>(val value: T) { a fun isNull(): Boolean {

    a return value != null } a } a val a1: A<Int?> = A(null) a a1.isNull() a val a2: A<Int> = A(10) a a2.isNull() a
  137. class A<T>(val value: T) a fun <T : Any> A<T?>.isNull():

    Boolean { a return value != null a } a val a1: A<Int?> = A(null) a a1.isNull() a val a2: A<Int> = A(10) a a2.isNull() a
  138. class A<T>(val value: T) a fun <T : Any> A<T?>.isNull():

    Boolean { a return value != null a } a val a1: A<Int?> = A(null) a a1.isNull() a val a2: A<Int> = A(10) a a2.isNull() a
  139. class A<T>(val value: T) a fun <T : Any> A<T?>.isNull():

    Boolean { a return value != null a } a val a1: A<Int?> = A(null) a a1.isNull() a val a2: A<Int> = A(10) a a2.isNull() a
  140. class A<T>(val value: T) a fun <T : Any> A<T?>.isNull():

    Boolean { a return value != null a } a val a1: A<Int?> = A(null) a a1.isNull() a val a2: A<Int> = A(10) a a2.isNull() a ❌
  141. • Smart Casts • AnyɺUnitɺNothing • δΣωϦΫε •Sealed class •

    ؔ਺ܕ
  142. Sealed class • ੍ݶ͞ΕͨαϒΫϥε֊૚ߏ଄Λ࡞Δ͜ͱ͕ग़དྷΔ • ಛघͳ༻్ͷabstract class

  143. abstract class Either object Left : Either() object Right :

    Either() when (obj) { a Left -> println("is Left") Right -> println("is Right") else -> println("else") } a
  144. sealed class Either object Left : Either() object Right :

    Either() when (obj) { a Left -> println("is Left") Right -> println("is Right") else -> println("else") } a
  145. sealed class Either object Left : Either() object Right :

    Either() when (obj) { a Left -> println("is Left") Right -> println("is Right") } a
  146. sealed͸classͰͷΈ༗ޮ • interfaceͩͱɺ༰қʹܧঝग़དྷͯ͠·͏ͨΊɺ੍໿ΛഁΕͯ ͠·͏

  147. public abstract class Either { private Either() { } //

    $FF: synthetic method public Either(DefaultConstructorMarker $constructor_marker) { this(); } }
  148. public abstract class Either { private Either() { } //

    $FF: synthetic method public Either(DefaultConstructorMarker $constructor_marker) { this(); } }
  149. • Smart Casts • AnyɺUnitɺNothing • δΣωϦΫε • Sealed class

    •ؔ਺ܕ
  150. ؔ਺ܕ • KotlinͰ͸ؔ਺ʢFunctionʣ͕ϑΝʔετΫϥεΦϒδΣΫτ • ม਺ɺؔ਺ͷҾ਺ɺ໭Γ஋ͳͲʹؔ਺ܕΛ࢖͏͜ͱ͕ग़དྷΔ

  151. ؔ਺ܕ • Function0 ~ Function22ͷ22Ҿ਺·Ͱͷؔ਺ΠϯλʔϑΣʔε ͱɺͦΕҎ্ͷҾ਺༻ͷɺFunctionNΠϯλʔϑΣʔε͕ఆٛ ͞Ε͍ͯΔ • ্هͷؔ਺ΠϯλʔϑΣʔεʹίϯύΠϧ࣌ʹม׵͞ΕΔ

  152. fun hoge(body: Function1<Int, String>) { a body(10) } a

  153. fun hoge(body: (Int) -> String) { a body(10) } a

  154. fun hoge(body: (Int) -> String) { a body(10) } a

    hoge { it.toString() } a
  155. fun add(a1: Int, a2: Int): Int { a return a1

    + a2 } a add add(10, 20)
  156. fun add(a1: Int, a2: Int): Int { a return a1

    + a2 } a add add(10, 20) val a: (Int, Int) -> Int = ::add
  157. fun add(a1: Int, a2: Int): Int { a return a1

    + a2 } a add add(10, 20) val a: (Int, Int) -> Int = ::add a(10, 20)
  158. } a add add(10, 20) val a: (Int, Int) ->

    Int = ::add a(10, 20) fun <P1, P2, R> ((P1, P2) -> R).curried(): (P1) -> (P2) -> R = { p1: P1 -> { p2: P2 -> this(p1, p2) } } a
  159. } a add add(10, 20) val a: (Int, Int) ->

    Int = ::add a(10, 20) fun <P1, P2, R> ((P1, P2) -> R).curried(): (P1) -> (P2) -> R = { p1: P1 -> { p2: P2 -> this(p1, p2) } } a
  160. } a add add(10, 20) val a: (Int, Int) ->

    Int = ::add a(10, 20) fun <P1, P2, R> ((P1, P2) -> R).curried(): (P1) -> (P2) -> R = { p1: P1 -> { p2: P2 -> this(p1, p2) } } a
  161. } a add add(10, 20) val a: (Int, Int) ->

    Int = ::add a(10, 20) fun <P1, P2, R> ((P1, P2) -> R).curried(): (P1) -> (P2) -> R = { p1: P1 -> { p2: P2 -> this(p1, p2) } } a val curried = a.curried()
  162. } a add add(10, 20) val a: (Int, Int) ->

    Int = ::add a(10, 20) fun <P1, P2, R> ((P1, P2) -> R).curried(): (P1) -> (P2) -> R = { p1: P1 -> { p2: P2 -> this(p1, p2) } } a val curried = a.curried() curried(10)(20)
  163. class A : (Int) -> Unit { a override fun

    invoke(p1: Int) { a println("call $p1") } a } a val a = A() a.invoke(10)
  164. class A : (Int) -> Unit { a override fun

    invoke(p1: Int) { a println("call $p1") } a } a val a = A() a(10)
  165. public interface Function1<in P1, out R> : Function<R> { public

    operator fun invoke(p1: P1): R } a
  166. public interface Function1<in P1, out R> : Function<R> { public

    operator fun invoke(p1: P1): R } a val a: (Number) -> Number = { it } a
  167. public interface Function1<in P1, out R> : Function<R> { public

    operator fun invoke(p1: P1): R } a val a: (Number) -> Number = { it } a val a1: (Int) -> Number = a
  168. public interface Function1<in P1, out R> : Function<R> { public

    operator fun invoke(p1: P1): R } a val a: (Number) -> Number = { it } a val a1: (Int) -> Number = a
  169. public interface Function1<in P1, out R> : Function<R> { public

    operator fun invoke(p1: P1): R } a val a: (Number) -> Number = { it } a val a1: (Int) -> Number = a val a2: (Number) -> Any = a
  170. public interface Function1<in P1, out R> : Function<R> { public

    operator fun invoke(p1: P1): R } a val a: (Number) -> Number = { it } as val a1: (Int) -> Number = a val a2: (Number) -> Any = a
  171. SAMม׵ • SAM? • Single Abstract Method • 1ͭͷந৅ϝιουΛ࣋ͭ •

    Kotlin͔ΒJavaఆٛͷSAMΛ࢖͏ͱ͖ʹɺϥϜμࣜͰ؆ܿʹ ॻ͘͜ͱ͕ग़དྷΔ
  172. public class SamTest { a public static void foo(Runnable a,

    Runnable b) { a } a } a fun test() { a SamTest.foo({}) { a } a } a
  173. public class SamTest { a public static void foo(Runnable a,

    Runnable b) { a } a } a fun test() { a SamTest.foo({}) { a } a } a public interface Runnable { public abstract void run(); }
  174. public class SamTest { a public static void foo(Runnable a,

    Runnable b) { a } a } a fun test(r: Runnable) { a SamTest.foo(r) { } } a
  175. public class SamTest { a public static void foo(Runnable a,

    Runnable b) { a } a } a fun test(r: Runnable) { a SamTest.foo(r) { } } a ❌
  176. KotlinͷSAMม׵ͷ՝୊ • ෳ਺ͷSAMΛҾ਺ʹऔΔ৔߹ɺ1ͭͰ΋࣮ମΛ࢖ͬͯ͠·͏ ͱɺҙਤͨ͠ม׵͕ߦΘΕͳ͍

  177. // RxJava val o1 = Observable.just(1) val o2 = Observable.just(2)

    val combination = Observable .combineLatest(o1, o2, { n1, n2 -> n1 to n2 }) a
  178. // RxJava val o1 = Observable.just(1) val o2 = Observable.just(2)

    val combination = Observable .combineLatest(o1, o2, { n1, n2 -> n1 to n2 }) public static <T1, T2, R> Observable<R> combineLatest( ObservableSource<? extends T1> source1, ObservableSource<? extends T2> source2, BiFunction<? super T1, ? super T2, ? extends R> combiner ) a
  179. // RxJava val o1 = Observable.just(1) val o2 = Observable.just(2)

    val combination = Observable .combineLatest(o1, o2, { n1, n2 -> n1 to n2 }) public static <T1, T2, R> Observable<R> combineLatest( ObservableSource<? extends T1> source1, ObservableSource<? extends T2> source2, BiFunction<? super T1, ? super T2, ? extends R> combiner ) a public interface ObservableSource<T> { a void subscribe(@NonNull Observer<? super T> observer); } ˇ
  180. // RxJava val o1 = Observable.just(1) val o2 = Observable.just(2)

    val combination = Observable .combineLatest(o1, o2, { n1, n2 -> n1 to n2 })
  181. // RxJava val o1 = Observable.just(1) val o2 = Observable.just(2)

    val combination = Observable .combineLatest(o1, o2, { n1, n2 -> n1 to n2 }) ❌
  182. // RxJava val o1 = Observable.just(1) val o2 = Observable.just(2)

    val combination = Observable .combineLatest(o1, o2, BiFunction { n1, n2 -> n1 to n2 })
  183. public static <T1, T2, R> Observable<R> combineLatest( ObservableSource<? extends T1>

    source1, ObservableSource<? extends T2> source2, BiFunction<? super T1, ? super T2, ? extends R> combiner ) a
  184. public static <T1, T2, R> Observable<R> combineLatest( Observable<? extends T1>

    source1, Observable<? extends T2> source2, BiFunction<? super T1, ? super T2, ? extends R> combiner ) a
  185. public static <T1, T2, R> Observable<R> combineLatest( Observable<? extends T1>

    source1, Observable<? extends T2> source2, BiFunction<? super T1, ? super T2, ? extends R> combiner ) a val o1 = Observable.just(1) val o2 = Observable.just(2) val combination = Observable .combineLatest(o1, o2, BiFunction { n1, n2 -> n1 to n2 })
  186. public static <T1, T2, R> Observable<R> combineLatest( Observable<? extends T1>

    source1, Observable<? extends T2> source2, BiFunction<? super T1, ? super T2, ? extends R> combiner ) a val o1 = Observable.just(1) val o2 = Observable.just(2) val combination = Observable .combineLatest(o1, o2, { n1, n2 -> n1 to n2 })
  187. NewInference • kotlinͰ͸SAMม׵ͷ໰୊ʹରͯ͠ɺ৽͍͠ܕਪ࿦Λ։ൃͯ͠ ͍Δ • ݱࡏɺexperimentalͷཱͪҐஔ͕ͩɺઃఆͰenableʹ͢Δ͜ͱ ͕Մೳ

  188. ·ͱΊ • KotlinͷSmart Castsͱܕਪ࿦Ͱɺ৑௕ͳίʔυΛݮΒ͠ɺҰ ෦μοΫλΠϐϯάͷΑ͏ͳॻ͖৺஍ΛಘΔ͜ͱ͕Մೳʂ • ॊೈͳδΣωϦΫεAPIΛ࢖͏͜ͱͰɺॊೈͳAPI͕ߏஙग़དྷ Δʂ • NothingܕΛ࢖͏͜ͱͰɺॊೈͳAPIΛߏஙͰ͖Δʂ

    • Sealed classΛ࢖͏͜ͱͰɺॊೈͳAPIΛߏஙͰ͖Δʂ
  189. Kotlin Fest 2019 ࠤ౻ ൏ / Sato Shun Twitter: @stsn_jp

    GitHub: satoshun Kotlinܕ࣮ફೖ໳