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

Kotlinもう一歩

 Kotlinもう一歩

Kotlinのタイプシステムとジェネリクスについて

kobito-kaba

August 25, 2018
Tweet

More Decks by kobito-kaba

Other Decks in Programming

Transcript

  1. Hiroyuki Mori
    @moridroid
    Kotlinもう一歩

    View Slide

  2. 本書きました!

    View Slide

  3. goo.gl/fW2YPh

    View Slide

  4. Kotlinもう一歩

    View Slide

  5. Kotlinのタイプシステム

    View Slide

  6. クラスとタイプ

    View Slide

  7. クラス ≠ タイプ

    View Slide

  8. // class: String, type: String
    val s1: String = "string"

    View Slide

  9. // class: String, type: String
    val s1: String = "string"
    // class: String, type: String?
    val s2 : String? = "string"

    View Slide

  10. タイプとは何か

    View Slide

  11. ・すべての変数や式には型がある
    // type: String
    val str : String = "string"
    // type: Char
    if (str.isNotEmpty()) str[0] else '\n'

    View Slide

  12. ・型によって、変数や式のとりうる値の範囲が決まる
    // type: String → 文字列
    val str : String = "string"
    // type: Char → 16-bit ユニコード文字
    if (str.isNotEmpty()) str[0] else '\n'

    View Slide

  13. ・型によって、行える演算や操作が決まる
    // 文字列は加算できる
    val s = "abc" + "def"
    // 整数はいろいろできる
    val i = 100 * (10 - 2) / (30 + 1)

    View Slide

  14. ・型によって、行える演算や操作が決まる
    // OK
    val str1 : String = "string"
    str1.hashCode()
    // nullableはいろいろできない
    val str2 : String? = "string"
    str2.hashCode() // NG

    View Slide

  15. だから安全!

    View Slide

  16. タイプとサブタイプ

    View Slide

  17. タイプAが期待されるすべての箇所で、
    タイプBが使用可能であれば、
    BはAのサブタイプ
    B <: A
    このとき、AはBのスーパータイプ

    View Slide

  18. val c : CharSequence = "abc" // OK
    fun foo(c : CharSequence) {}
    foo("abc") // OK
    fun bar() : CharSequence = "abc" // OK

    View Slide

  19. val c : CharSequence = "abc" // OK
    fun foo(c : CharSequence) {}
    foo("abc") // OK
    fun bar() : CharSequence = "abc" // OK

    View Slide

  20. val c : CharSequence = "abc" // OK
    fun foo(c : CharSequence) {}
    foo("abc") // OK
    fun bar() : CharSequence = "abc" // OK

    View Slide

  21. // Int <: Number
    val num1 : Number = 100
    // Double <: Number
    val num2 : Number = 10.0
    // Long <: Number
    val num3 : Number = 100L

    View Slide

  22. Int, Long, Double, … <: Number
    Number
    Long Int
    Double Float
    Short
    Byte

    View Slide

  23. Int型はNumber型の範囲内
    Number
    Int
    OK
    Long Int
    Double Float
    Short
    Byte

    View Slide

  24. Number型は、Int型の範囲内とは限らない
    Number
    Int
    NG
    Long Int
    Double Float
    Short
    Byte DoubleやLongかも?

    View Slide

  25. クイズ

    View Slide

  26. Kotlinのタイプシステムでは、
    Int型はInt型の…
    (A) サブタイプ
    (B) スーパータイプ
    (C) どちらでもない
    (D) どちらでもある

    View Slide

  27. Kotlinのタイプシステムでは、
    Int型はInt型の…
    (A) サブタイプ
    (B) スーパータイプ
    (C) どちらでもない
    (D) どちらでもある

    View Slide

  28. In Kotlin in Action

    View Slide

  29. View Slide

  30. val intType = Int::class.createType()
    intType.isSubtypeOf(intType)
    > true
    intType.isSupertypeOf(intType)
    > true

    View Slide

  31. View Slide

  32. Any

    View Slide

  33. // Int <: Any
    val any1 : Any = 100
    // Double <: Any
    val any2 : Any = 10.0
    // String <: Any
    val any3 : Any = "str"

    View Slide

  34. // String? <: Any ……...?
    val any4 : Any = null as String?

    View Slide

  35. View Slide

  36. Nothing

    View Slide

  37. // Why does this work?
    fun bar() : Int = TODO()

    View Slide

  38. // Why does this work?
    fun bar() : Int = TODO()
    val str1 : String = TODO()
    fun foo(l : List) = {}
    foo(TODO())

    View Slide

  39. public inline fun TODO(): Nothing =
    throw NotImplementedError()
    public class Nothing private constructor()

    View Slide

  40. fun nothing() : Nothing =
    throw Exception("nothing")
    val a : Number = nothing()
    val b : String = nothing()
    val c : List = nothing()

    View Slide

  41. View Slide

  42. nullableとnon-null

    View Slide

  43. // String <: String?
    val str1 : String? = "str" // OK
    fun foo(s : String?) {}
    foo("abc") // OK
    fun bar() : String? = "abc" // OK

    View Slide

  44. // String <: String?
    val str1 : String? = "str" // OK
    // String? <: String ……..?
    val str2 : String = str1
    // NonNull <: Nullable

    View Slide

  45. View Slide

  46. まとめ

    View Slide

  47. View Slide

  48. Generics

    View Slide

  49. fun toString(i : Int) = i.toString()
    fun toString(l : Long) = l.toString()
    fun toString(f : Float) = d.toString()
    ...

    View Slide

  50. fun toString(t : T) = t.toString()

    View Slide

  51. fun toDouble(i : Int) = i.toDouble()
    fun toDouble(l : Long) = l.toDouble()
    fun toDouble(f : Float) = f.toDouble()
    ...

    View Slide

  52. fun toDouble(t : T) = t.toDouble()

    View Slide

  53. 上限境界

    View Slide

  54. fun toDouble(t : T)
    = t.toDouble()

    View Slide

  55. fun copyWhenGreater(list: List, threshold: T)
    : List
    where T : CharSequence,
    T : Comparable {
    return list.filter { it > threshold }
    .map { it.toString() }
    }

    View Slide

  56. fun copyWhenGreater(list: List, threshold: T)
    : List
    where T : CharSequence,
    T : Comparable {
    return list.filter { it > threshold }
    .map { it.toString() }
    }

    View Slide

  57. 型引数とnullability

    View Slide

  58. fun foo(t : T) = t.hashCode()

    View Slide

  59. fun foo(t : T) = t.hashCode()

    View Slide

  60. fun foo(t : T) = t.hashCode()
    fun foo(t : T) = t?.hashCode()

    View Slide

  61. Type Erasure

    View Slide

  62. // Kotlin Code: List
    val list : List = listOf()

    View Slide

  63. // Kotlin Code: List
    val list : List = listOf()
    // Decompiled : List
    List list = CollectionsKt.emptyList();

    View Slide

  64. if (list is List) {
    // You can't do this
    }

    View Slide

  65. 変位

    View Slide

  66. Int <: Number

    View Slide

  67. Int <: Number
    val number : Number = 123

    View Slide

  68. Int <: Number
    List <: List

    View Slide

  69. Int <: Number
    List <: List
    val nums : List = listOf(1, 2, 3)

    View Slide

  70. Int <: Number
    List <: List
    MutableList <: MutableList

    View Slide

  71. Int <: Number
    List <: List
    MutableList <: MutableList
    val nums : MutableList = mutableListOf(1, 2, 3)

    View Slide

  72. タイプAが期待されるすべての箇所で、
    タイプBが使用可能であれば、
    BはAのサブタイプ

    View Slide

  73. MutableListは、
    MutableListの
    代わりに使えない場合がある

    View Slide

  74. // もしこれが可能なら
    val nums : MutableList
    = mutableListOf(1, 2, 3)
    // これができてしまう
    nums.add(10.5)

    View Slide

  75. val nums = mutableListOf(1, 2, 3)
    val ints = mutableListOf(1, 2, 3)
    val num1 : Number = nums[0] // OK
    val num2 : Number = ints[0] // OK
    nums.add(10.0) // OK
    ints.add(10.0) // NG

    View Slide

  76. 変位
    B <: A のときに、
    Foo と Fooにどういう関係があるか

    View Slide

  77. invariant, covariant, contravariant
     不変   共変    反変   

    View Slide

  78. invariant, covariant, contravariant
    B <: A のとき、
    Foo <: Foo でもなく
    Foo <: Foo でもない

    View Slide

  79. class Invariant(val value : T)
    invariant, covariant, contravariant

    View Slide

  80. class Invariant(val value : T)
    val num : Invariant
    = Invariant(100)

    View Slide

  81. class Invariant(val value : T)
    val num : Invariant
    = Invariant(100)
    val int : Invariant
    = Invariant(100)

    View Slide

  82. invariant, covariant, contravariant
    B <: A のとき、Foo <: Foo

    View Slide

  83. invariant, covariant, contravariant
    class Covariant(val value: T)

    View Slide

  84. class Covariant(val value: T)
    val num : Covariant
    = Covariant(100)
    invariant, covariant, contravariant

    View Slide

  85. class Covariant(val value: T)
    val num : Covariant
    = Covariant(100)
    val int : Covariant
    = Covariant(100)
    invariant, covariant, contravariant

    View Slide

  86. invariant, covariant, contravariant
    B <: Aのとき、Foo <: Foo

    View Slide

  87. class Contravariant(value: T)
    invariant, covariant, contravariant

    View Slide

  88. class Contravariant(value: T)
    val num : Contravariant
    = Contravariant(100)
    invariant, covariant, contravariant

    View Slide

  89. class Contravariant(value: T)
    val num : Contravariant
    = Contravariant(100)
    val int : Contravariant
    = Contravariant(10.0)
    invariant, covariant, contravariant

    View Slide

  90. 不変 共変 反変

    サブタイプを
    引き継がない
    サブタイプを
    引き継ぐ
    サブタイプが
    逆転する

    View Slide

  91. inとout

    View Slide

  92. out

    View Slide

  93. class Covariant (t: T) {
    val value1 = t
    var value2 = t
    fun get() : T = value1
    fun set(t: T) { value2 = t }
    }

    View Slide

  94. class Covariant (t: T) {
    val value = t
    fun get() : T = value
    }

    View Slide

  95. val num1 : Number = 100
    val num2 : Number
    = Covariant(100).get()

    View Slide

  96. public interface List : Collection {

    View Slide

  97. in

    View Slide

  98. class Contravariant (t: T) {
    val value1 = t
    var value2 = t
    fun get() : T = value1
    fun set(t: T) { }
    }

    View Slide

  99. class Contravariant (t: T) {
    fun set(t: T) { }
    }

    View Slide

  100. val num = Contravariant(100)
    num.set(1234567L)
    num.set(10.0)
    num.set(123) // OK!

    View Slide

  101. class Contravariant (t: T) {
    fun set(t: T) { }
    }

    View Slide

  102. class Contravariant (t: T) {
    private var value : T = t
    private fun get() : T = value
    fun set(t: T) { value = t }
    }

    View Slide

  103. 不変 共変 反変

    サブタイプを
    引き継がない
    サブタイプを
    引き継ぐ
    サブタイプが
    逆転する
    Tは
    どこでも使用可
    Tは
    戻り値だけ
    Tは
    引数だけ

    View Slide

  104. Type Projection

    View Slide

  105. MutableList <: MutableList

    View Slide

  106. MutableList <: MutableList
    val nums : MutableList
    = mutableListOf(1, 2, 3)

    View Slide

  107. MutableList <: MutableList
    val nums : MutableList
    = mutableListOf(1, 2, 3)
    val nums : MutableList
    = mutableListOf(1.0, 2.0, 3.0)

    View Slide

  108. class Foo
    val foo : Foo
    class Bar
    val bar : Bar

    View Slide

  109. 余談

    View Slide

  110. val nums : MutableList
    = mutableListOf(1, 2, 3)

    View Slide

  111. val nums : MutableList = mutableListOf(1, 2, 3)
    val constructor = Nothing::class.java.getDeclaredConstructor()
    constructor.isAccessible = true
    val nothing = constructor.newInstance()

    View Slide

  112. val nums : MutableList = mutableListOf(1, 2, 3)
    val constructor = Nothing::class.java.getDeclaredConstructor()
    constructor.isAccessible = true
    val nothing = constructor.newInstance()
    nums.add(nothing)

    View Slide

  113. val nums : MutableList = mutableListOf(1, 2, 3)
    val constructor = Nothing::class.java.getDeclaredConstructor()
    constructor.isAccessible = true
    val nothing = constructor.newInstance()
    nums.add(nothing)
    print(nums)
    > [1, 2, 3, java.lang.Void@5e9d7b78]

    View Slide

  114. Star Projection

    View Slide

  115. // Java Way
    List> list;

    View Slide

  116. // Java Way
    List> list;
    // Kotlin Way
    val list : List<*>

    View Slide

  117. // Java Way
    List> list;
    // Kotlin Way
    val list : List<*> // List

    View Slide

  118. // List
    val list : List<*> = listOf(1, 2, 3)
    // This is safe
    val foo : Any? = list[0]

    View Slide

  119. // MutableList
    val list : MutableList<*>
    = mutableListOf(1, 2, 3)
    // This is not safe
    list.add(4.0)

    View Slide

  120. Star Projection
    と変位アノテーション

    View Slide

  121. out

    View Slide

  122. class Foo(val value : T)

    View Slide

  123. class Foo(val value : T)
    val foo : Foo<*> = Foo(1)

    View Slide

  124. class Foo(val value : T)
    val foo : Foo<*> = Foo(1)
    // Foo

    View Slide

  125. in

    View Slide

  126. class Foo {
    fun foo(t : T) {}
    }

    View Slide

  127. class Foo {
    fun foo(t : T) {}
    }
    val foo : Foo<*> = Foo()

    View Slide

  128. class Foo {
    fun foo(t : T) {}
    }
    val foo : Foo<*> = Foo()
    // Foo

    View Slide

  129. class Foo {
    fun foo(t : T) {}
    }
    val foo : Foo<*> = Foo()
    // Foo

    View Slide

  130. View Slide

  131. class Foo {
    fun foo(t : T) {}
    }
    val foo : Foo<*> = Foo()
    // Foo

    View Slide

  132. class Foo {
    fun foo(t : T) {}
    }
    val foo : Foo<*> = Foo()
    // Foo
    foo.foo(1) // requires Nothing

    View Slide

  133. invariant

    View Slide

  134. class Foo {
    fun foo() : T = TODO()
    fun bar(t : T) {}
    }

    View Slide

  135. class Foo {
    fun foo() : T = TODO()
    fun bar(t : T) {}
    }
    val foo : Foo<*> = Foo()

    View Slide

  136. class Foo {
    fun foo() : T = TODO()
    fun bar(t : T) {}
    }
    val foo : Foo<*> = Foo()
    val n = foo.foo() // Foo

    View Slide

  137. class Foo {
    fun foo() : T = TODO()
    fun bar(t : T) {}
    }
    val foo : Foo<*> = Foo()
    val n = foo.foo() // Foo
    foo.bar(n) // Foo

    View Slide

  138. まとめ

    View Slide

  139. 不変 共変 反変

    サブタイプを
    引き継がない
    サブタイプを
    引き継ぐ
    サブタイプが
    逆転する
    Tは
    どこでも使用可
    Tは
    戻り値だけ
    Tは
    引数だけ

    View Slide

  140. class Foo
    Foo<*> // Foo
    class Bar
    Bar<*> // Bar

    View Slide

  141. class Foo
    Foo<*> // Foo
    class Bar
    Bar<*> // Bar

    View Slide

  142. class Foo
    Foo<*> // Foo : out position
    // Foo : in position
    class Bar
    Bar<*> // Bar : out position
    // Bar : in position

    View Slide

  143. Hiroyuki Mori
    @moridroid
    Thank you

    View Slide