$30 off During Our Annual Pro Sale. View Details »

Kotlin Fest 2019: Kotlin型実践入門

Sato Shun
August 24, 2019

Kotlin Fest 2019: Kotlin型実践入門

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

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

Sato Shun

August 24, 2019
Tweet

More Decks by Sato Shun

Other Decks in Technology

Transcript

  1. Kotlin Fest
    2019
    ࠤ౻ ൏ / Sato Shun

    Twitter: @stsn_jp

    GitHub: satoshun
    Kotlinܕ࣮ફೖ໳

    View Slide

  2. ֓ཁ
    • KotlinͰ͸Javaʹ͸ͳ͍༷ʑͳܕʹؔ͢Δػೳ͕௥Ճ͞Εͨ
    ͷͰɺͦΕΒͷղઆ

    • ॳֶऀ޲͚ͷ಺༰ʹͳ͓ͬͯΓ·͢

    View Slide

  3. ໨࣍
    • Smart Casts

    • AnyɺUnitɺNothing

    • δΣωϦΫε

    • Sealed class

    • ؔ਺ܕ

    View Slide

  4. •Smart Casts
    • AnyɺUnitɺNothing

    • δΣωϦΫε

    • Sealed class

    • ؔ਺ܕ

    View Slide

  5. Smart Casts
    • ifࣜɺwhenࣜɺisɺasͳͲͷ࣮ߦޙʹɺ໌ࣔతʹܕΩϟετ
    ͠ͳͯ͘΋ɺܕΛਪ࿦ͯ͘͠ΕΔ

    • flow-sensitive typing (flow typing)ͱݺ͹ΕΔܕγεςϜ

    View Slide

  6. Smart Casts
    • ifࣜɺwhenࣜɺisɺasͳͲͷ࣮ߦޙʹɺ໌ࣔతʹܕΩϟετ
    ͠ͳͯ͘΋ɺܕΛਪ࿦ͯ͘͠ΕΔ

    • flow-sensitive typing (flow typing)ͱݺ͹ΕΔܕγεςϜ

    • ৑௕ͳܕΩϟετΛܰݮ͢Δ

    • ಈతܕ෇͚ݴޠͷμοΫλΠϐϯάͷΑ͏ͳॻ͖৺஍

    • https://en.wikipedia.org/wiki/Flow-sensitive_typing

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

  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

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  19. val strs: List? = …
    a
    if (!strs.isNullOrEmpty()) {
    a
    println(strs!!.size)
    }
    a

    View Slide

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

    View Slide

  21. Contracts
    • Smart CastsΛ֦ு͢Δػೳ

    • ؔ਺ݺͼग़͠ͷ݁ՌΛ΋ͱʹɺSmart Casts͢Δ͜ͱ͕ग़དྷ
    Δ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  26. val strs: List? = …
    a
    if (!strs.isNullOrEmpty()) {
    a
    println(strs!!.size)
    }
    a

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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)

    View Slide

  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)

    View Slide

  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)

    View Slide

  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)

    View Slide

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

    View Slide

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

    View Slide

  36. public inline fun 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

    View Slide

  37. public inline fun 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

    View Slide

  38. fun checkObj(obj: Any?): Boolean {
    a
    return obj != null
    }
    a
    if (checkObj(obj)) {
    a
    obj!!.javaClass
    }
    a

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  44. • Smart Casts

    •AnyɺUnitɺNothing
    • δΣωϦΫε

    • Sealed class

    • ؔ਺ܕ

    View Slide

  45. Anyܕ
    • ͢΂ͯͷKotlinͷΫϥεͷεʔύʔΫϥε

    • ϧʔτΫϥε

    • Javaͷ৔߹ɺjava.lang.Object͕ϧʔτΫϥε

    View Slide

  46. Anyܕ
    • JavaͷObjectͱҧ͏఺͸Ͳ͔͜ʁ

    • waitɺnotifyϝιου͕࢖͑ͳ͍

    • ໌ࣔతʹjava.lang.ObjectܕʹΩϟετ͢Ε͹ݺͼग़ͤΔ

    • getClassϝιου͕֦ுؔ਺ʹ

    • public inline val T.javaClass: Class

    • cloneɺfinalizeϝιου

    View Slide

  47. val s = ""
    s.notify()

    View Slide

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

    View Slide

  49. Unitܕ
    • JavaͰ͍͏ͱ͜ΖͷvoidΛදݱ͢ΔΫϥε

    • ฦΓ஋͕ۭͰ͋Δ͜ͱΛද͢

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  54. Nothingܕ
    • ͢΂ͯͷKotlinͷΫϥεͷαϒΫϥε

    • ஋͕ଘࡏ͠ͳ͍͜ͱΛࣔ͢

    • ਖ਼ৗऴྃ͢Δ͜ͱ͕ͳ͍ؔ਺ͷฦΓ஋ʹ࢖͑Δ

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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)

    View Slide

  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)

    View Slide

  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)

    View Slide

  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)

    View Slide

  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)

    View Slide

  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)

    View Slide

  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)

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  69. // ඪ४ؔ਺
    public inline fun TODO(): Nothing = throw
    NotImplementedError()
    // KotlinTest
    fun fail(msg: String): Nothing = throw
    Failures.failure(msg)

    View Slide

  70. // Kotlin/kotlinx.collections.immutable
    internal companion object {
    internal val EMPTY = TrieNode(0, emptyArray())
    }
    // airbnb/MvRx
    object Uninitialized : Async(complete = false,
    shouldLoad = true), Incomplete

    View Slide

  71. fun test2() {
    a
    while (true) {
    a
    println(".")
    }
    a
    }
    a

    View Slide

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

    View Slide

  73. Nothing?ܕ
    • Nothing?ܕ΋ଘࡏ͢Δ

    • Nothing͸஋ͱͯ͠ଘࡏ͠ͳ͍ͷͰɺnullͷΈΛڐՄ͢Δ

    View Slide

  74. // kotlintest/kotlintest
    interface Show {
    a
    fun supports(a: Any?): Boolean
    fun show(a: A): String
    }
    a
    object NullShow : Show {
    a
    override fun supports(a: Any?): Boolean = a == null
    override fun show(a: Nothing?): String = ""
    }
    a

    View Slide

  75. • Smart Casts

    • AnyɺUnitɺNothing

    •δΣωϦΫε
    • Sealed class

    • ؔ਺ܕ

    View Slide

  76. δΣωϦΫε
    • ෼ࢄΞϊςʔγϣϯʢvariance annotationʣ

    • outɺinम০ࢠ

    • એݴଆมੑ: declaration-site variance

    • where

    • reified

    • ֦ுؔ਺ + δΣωϦΫε

    View Slide

  77. ෼ࢄΞϊςʔγϣϯ
    • out - ڞม: covariance

    • in - ൓ม: contravariance

    • ࢦఆͳ͠: ෆม: invariance

    View Slide

  78. ڞมɺ൓มɺෆม
    • Number <|- Intͷܧঝؔ܎͕͋Δ

    View Slide

  79. ڞมɺ൓มɺෆม
    • Number <|- Intͷܧঝؔ܎͕͋Δ

    • A <|- Aͷ৔߹ɺA͸ڞมͰ͋Δ

    View Slide

  80. ڞมɺ൓มɺෆม
    • Number <|- Intͷܧঝؔ܎͕͋Δ

    • A <|- Aͷ৔߹ɺA͸ڞมͰ͋Δ

    View Slide

  81. ڞมɺ൓มɺෆม
    • Number <|- Intͷܧঝؔ܎͕͋Δ

    • A <|- Aͷ৔߹ɺA͸ڞมͰ͋Δ

    • A -|> Aͷ৔߹ɺA͸൓มͰ͋Δ

    View Slide

  82. ڞมɺ൓มɺෆม
    • Number <|- Intͷܧঝؔ܎͕͋Δ

    • A <|- Aͷ৔߹ɺA͸ڞมͰ͋Δ

    • A -|> Aͷ৔߹ɺA͸൓มͰ͋Δ

    View Slide

  83. ڞมɺ൓มɺෆม
    • Number <|- Intͷܧঝؔ܎͕͋Δ

    • A <|- Aͷ৔߹ɺA͸ڞมͰ͋Δ

    • A -|> Aͷ৔߹ɺA͸൓มͰ͋Δ

    • Aɺ A͕ؔ܎ͳ͍৔߹ɺA͸ෆมͰ͋Δ

    View Slide

  84. ڞมɺ൓มɺෆม
    • Number <|- Intͷܧঝؔ܎͕͋Δ

    • A <|- Aͷ৔߹ɺA͸ڞมͰ͋Δ

    • A -|> Aͷ৔߹ɺA͸൓มͰ͋Δ

    • Aɺ A͕ؔ܎ͳ͍৔߹ɺA͸ෆมͰ͋Δ

    View Slide

  85. // ڞม
    val a: A = A()
    a
    val b: A = a

    View Slide

  86. // ڞม
    val a: A = A()
    a
    val b: A = a
    // ൓ม
    val a: A = A()
    a
    val b: A = a

    View Slide

  87. // ڞม
    val a: A = A()
    a
    val b: A = a
    // ൓ม
    val a: A = A()
    a
    val b: A = a
    // ෆม
    val a: A = A()
    a

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  96. ListͱMutableList
    public interface List : Collection

    public interface MutableList : List, …

    View Slide

  97. ListͱMutableList
    public interface List : Collection

    public interface MutableList : List, …

    • List͸outम০ࢠ͕෇͍͍ͯΔͷͰɺڞม

    • MutableList͸Կ΋෇͍͍ͯͳ͍ͷͰɺෆม

    View Slide

  98. val strs: List = listOf("a", “b")

    View Slide

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

    View Slide

  100. val strs: List = listOf("a", “b")
    val anys: List = strs
    val a: Any = anys[0]

    View Slide

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

    View Slide

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

    View Slide

  103. val strs: MutableList = mutableListOf("a", "b")

    View Slide

  104. val strs: MutableList = mutableListOf("a", "b")
    val anys: MutableList = strs

    View Slide

  105. val strs: MutableList = mutableListOf("a", "b")
    val anys: MutableList = strs
    anys.add(10)

    View Slide

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

    View Slide

  107. val strs: MutableList = mutableListOf("a", "b")
    val anys: MutableList = strs
    anys.add(10)
    val str: String = strs.last()

    View Slide

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

    View Slide

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

    View Slide

  110. PECS
    • Producer Extends Consumer Super

    • Producer͸readͷੑ࣭Λ࣋ͭ

    • Consumer͸writeͷੑ࣭Λ࣋ͭ

    • List͸Producerͷੑ࣭ͷΈΛ࣋ͭͷͰɺExtends = out ڞมʹ
    ग़དྷΔ

    • MutableList͸ProducerͱConsumerͷੑ࣭Λ࣋ͭͷͰɺෆม

    View Slide

  111. 2ͭҎ্ͷ্քΛ࣋ͭܕม਺
    • 1ͭͷ্քʢupper boundʣΛ࣋ͭͱ͖͸ɺׅހ಺ʹॻ͚͹ྑ
    ͍

    View Slide

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

    • fun hoge(t: T) {…}

    View Slide

  113. 2ͭҎ্ͷ্քΛ࣋ͭܕม਺
    • 1ͭͷ্քʢupper boundʣΛ࣋ͭͱ͖͸ɺׅހ಺ʹॻ͚͹ྑ
    ͍

    • fun hoge(t: T) {…}

    • 2ͭҎ্ͷ্քΛ࣋ͭ৔߹͸Ͳ͏͢Ε͹Α͍͔ʁ

    • ྫ͑͹ɺActivity͔ͭOnClickListenerΛ࣋ͭܕΛड͚ೖΕΔܕ
    ม਺Λఆ͍ٛͨ͠

    View Slide

  114. class OnClickActivity() : Activity(), OnClickListener

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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)

    View Slide

  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)

    View Slide

  120. fun setClick(activity: OnClickActivity) {
    a
    }
    a

    View Slide

  121. fun setClick(activity: T)

    View Slide

  122. fun setClick(activity: T)
    where T : Activity,
    T : OnClickListener {
    a
    }
    a

    View Slide

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

    View Slide

  124. fun setClick(activity: T)
    where T : Activity,
    T : OnClickListener {
    }
    val activity = OnClickActivity()
    setClick(activity)
    val activity2 = OnClickActivity2()
    setClick(activity2)

    View Slide

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

    View Slide

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

    View Slide

  127. internal abstract class NIOSocketImpl(
    override val channel: S,
    val selector: SelectorManager,
    val pool: ObjectPool?
    ) : 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(channel, selector,
    DefaultDatagramByteBufferPool)
    Ktor

    View Slide

  128. internal abstract class NIOSocketImpl(
    override val channel: S,
    val selector: SelectorManager,
    val pool: ObjectPool?
    ) : 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(channel, selector,
    DefaultDatagramByteBufferPool)
    internal class SocketImpl(
    override val channel: S,
    private val socket: java.net.Socket,
    selector: SelectorManager
    ) : NIOSocketImpl(channel, selector, pool = null), Socket
    Ktor

    View Slide

  129. reified
    • ؔ਺಺͔Βܕม਺ʹΞΫηεग़དྷΔ

    • JavaͰ͸ܕม਺ʹϥϯλΠϜ࣌ʹΞΫηεͰ͖ͳ͍

    • Type Erasureͱݺ͹ΕΔݴޠ࢓༷ͷͨΊɺίϯύΠϧޙʹܕม਺͕
    ࡟আ͞ΕΔͨΊ

    View Slide

  130. inline fun hoge(obj: Any) {
    a
    println(T::class.java)
    a
    if (obj is T) {
    a
    println("obj is T")
    a
    }
    a
    }
    a

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  136. class A(val value: T) {
    a
    fun isNull(): Boolean {
    a
    return value != null
    }
    a
    }
    a
    val a1: A = A(null)
    a
    a1.isNull()
    a
    val a2: A = A(10)
    a
    a2.isNull()
    a

    View Slide

  137. class A(val value: T)
    a
    fun A.isNull(): Boolean {
    a
    return value != null
    a
    }
    a
    val a1: A = A(null)
    a
    a1.isNull()
    a
    val a2: A = A(10)
    a
    a2.isNull()
    a

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  141. • Smart Casts

    • AnyɺUnitɺNothing

    • δΣωϦΫε

    •Sealed class
    • ؔ਺ܕ

    View Slide

  142. Sealed class
    • ੍ݶ͞ΕͨαϒΫϥε֊૚ߏ଄Λ࡞Δ͜ͱ͕ग़དྷΔ

    • ಛघͳ༻్ͷabstract class

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

  146. sealed͸classͰͷΈ༗ޮ
    • interfaceͩͱɺ༰қʹܧঝग़དྷͯ͠·͏ͨΊɺ੍໿ΛഁΕͯ
    ͠·͏

    View Slide

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

    View Slide

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

    View Slide

  149. • Smart Casts

    • AnyɺUnitɺNothing

    • δΣωϦΫε

    • Sealed class

    •ؔ਺ܕ

    View Slide

  150. ؔ਺ܕ
    • KotlinͰ͸ؔ਺ʢFunctionʣ͕ϑΝʔετΫϥεΦϒδΣΫτ

    • ม਺ɺؔ਺ͷҾ਺ɺ໭Γ஋ͳͲʹؔ਺ܕΛ࢖͏͜ͱ͕ग़དྷΔ

    View Slide

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

    • ্هͷؔ਺ΠϯλʔϑΣʔεʹίϯύΠϧ࣌ʹม׵͞ΕΔ

    View Slide

  152. fun hoge(body: Function1) {
    a
    body(10)
    }
    a

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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)

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  165. public interface Function1 : Function {
    public operator fun invoke(p1: P1): R
    }
    a

    View Slide

  166. public interface Function1 : Function {
    public operator fun invoke(p1: P1): R
    }
    a
    val a: (Number) -> Number = { it }
    a

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  171. SAMม׵
    • SAM?

    • Single Abstract Method

    • 1ͭͷந৅ϝιουΛ࣋ͭ

    • Kotlin͔ΒJavaఆٛͷSAMΛ࢖͏ͱ͖ʹɺϥϜμࣜͰ؆ܿʹ
    ॻ͘͜ͱ͕ग़དྷΔ

    View Slide

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

    View Slide

  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();
    }

    View Slide

  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

    View Slide

  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

    View Slide

  176. KotlinͷSAMม׵ͷ՝୊
    • ෳ਺ͷSAMΛҾ਺ʹऔΔ৔߹ɺ1ͭͰ΋࣮ମΛ࢖ͬͯ͠·͏
    ͱɺҙਤͨ͠ม׵͕ߦΘΕͳ͍

    View Slide

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

    View Slide

  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 Observable combineLatest(
    ObservableSource extends T1> source1,
    ObservableSource extends T2> source2,
    BiFunction super T1, ? super T2, ? extends R>
    combiner
    )
    a

    View Slide

  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 Observable combineLatest(
    ObservableSource extends T1> source1,
    ObservableSource extends T2> source2,
    BiFunction super T1, ? super T2, ? extends R>
    combiner
    )
    a
    public interface ObservableSource {
    a
    void subscribe(@NonNull Observer super T> observer);
    }
    ˇ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  185. public static Observable 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
    })

    View Slide

  186. public static Observable 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
    })

    View Slide

  187. NewInference
    • kotlinͰ͸SAMม׵ͷ໰୊ʹରͯ͠ɺ৽͍͠ܕਪ࿦Λ։ൃͯ͠
    ͍Δ

    • ݱࡏɺexperimentalͷཱͪҐஔ͕ͩɺઃఆͰenableʹ͢Δ͜ͱ
    ͕Մೳ

    View Slide

  188. ·ͱΊ
    • KotlinͷSmart Castsͱܕਪ࿦Ͱɺ৑௕ͳίʔυΛݮΒ͠ɺҰ
    ෦μοΫλΠϐϯάͷΑ͏ͳॻ͖৺஍ΛಘΔ͜ͱ͕Մೳʂ

    • ॊೈͳδΣωϦΫεAPIΛ࢖͏͜ͱͰɺॊೈͳAPI͕ߏஙग़དྷ
    Δʂ

    • NothingܕΛ࢖͏͜ͱͰɺॊೈͳAPIΛߏஙͰ͖Δʂ

    • Sealed classΛ࢖͏͜ͱͰɺॊೈͳAPIΛߏஙͰ͖Δʂ

    View Slide

  189. Kotlin Fest
    2019
    ࠤ౻ ൏ / Sato Shun

    Twitter: @stsn_jp

    GitHub: satoshun
    Kotlinܕ࣮ફೖ໳

    View Slide