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

Kotlinもう一歩

 Kotlinもう一歩

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

kobito-kaba

August 25, 2018
Tweet

More Decks by kobito-kaba

Other Decks in Programming

Transcript

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

    // class: String, type: String? val s2 : String? = "string"
  2. ・型によって、変数や式のとりうる値の範囲が決まる // type: String → 文字列 val str : String =

    "string" // type: Char → 16-bit ユニコード文字 if (str.isNotEmpty()) str[0] else '\n'
  3. ・型によって、行える演算や操作が決まる // OK val str1 : String = "string" str1.hashCode()

    // nullableはいろいろできない val str2 : String? = "string" str2.hashCode() // NG
  4. val c : CharSequence = "abc" // OK fun foo(c

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

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

    : CharSequence) {} foo("abc") // OK fun bar() : CharSequence = "abc" // OK
  7. // Int <: Number val num1 : Number = 100

    // Double <: Number val num2 : Number = 10.0 // Long <: Number val num3 : Number = 100L
  8. Any

  9. // Int <: Any val any1 : Any = 100

    // Double <: Any val any2 : Any = 10.0 // String <: Any val any3 : Any = "str"
  10. // Why does this work? fun bar() : Int =

    TODO() val str1 : String = TODO() fun foo(l : List<Double>) = {} foo(TODO())
  11. fun nothing() : Nothing = throw Exception("nothing") val a :

    Number = nothing() val b : String = nothing() val c : List<Any> = nothing()
  12. // String <: String? val str1 : String? = "str"

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

    // OK // String? <: String ……..? val str2 : String = str1 // NonNull <: Nullable
  14. fun toString(i : Int) = i.toString() fun toString(l : Long)

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

    = l.toDouble() fun toDouble(f : Float) = f.toDouble() ...
  16. fun <T> copyWhenGreater(list: List<T>, threshold: T) : List<String> where T

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

    : CharSequence, T : Comparable<T> { return list.filter { it > threshold } .map { it.toString() } }
  18. fun <T> foo(t : T) = t.hashCode() fun <T :

    Any?> foo(t : T) = t?.hashCode()
  19. // Kotlin Code: List<String> val list : List<String> = listOf()

    // Decompiled : List List list = CollectionsKt.emptyList();
  20. Int <: Number List<Int> <: List<Number> MutableList<Int> <: MutableList<Number> val

    nums : MutableList<Number> = mutableListOf<Int>(1, 2, 3)
  21. val nums = mutableListOf<Number>(1, 2, 3) val ints = mutableListOf<Int>(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
  22. class Invariant<T>(val value : T) val num : Invariant<Number> =

    Invariant<Int>(100) val int : Invariant<Int> = Invariant<Number>(100)
  23. class Covariant<out T>(val value: T) val num : Covariant<Number> =

    Covariant<Int>(100) invariant, covariant, contravariant
  24. class Covariant<out T>(val value: T) val num : Covariant<Number> =

    Covariant<Int>(100) val int : Covariant<Int> = Covariant<Number>(100) invariant, covariant, contravariant
  25. class Contravariant<in T>(value: T) val num : Contravariant<Number> = Contravariant<Int>(100)

    val int : Contravariant<Int> = Contravariant<Number>(10.0) invariant, covariant, contravariant
  26. 不変 共変 反変 <T> <out T> <in T> サブタイプを 引き継がない

    サブタイプを 引き継ぐ サブタイプが 逆転する
  27. out

  28. class Covariant<out T> (t: T) { val value1 = t

    var value2 = t fun get() : T = value1 fun set(t: T) { value2 = t } }
  29. val num1 : Number = 100 val num2 : Number

    = Covariant<Int>(100).get()
  30. in

  31. class Contravariant<in T> (t: T) { val value1 = t

    var value2 = t fun get() : T = value1 fun set(t: T) { } }
  32. class Contravariant<in T> (t: T) { private var value :

    T = t private fun get() : T = value fun set(t: T) { value = t } }
  33. 不変 共変 反変 <T> <out T> <in T> サブタイプを 引き継がない

    サブタイプを 引き継ぐ サブタイプが 逆転する Tは どこでも使用可 Tは 戻り値だけ Tは 引数だけ
  34. MutableList<Int> <: MutableList<Number> val nums : MutableList<out Number> = mutableListOf<Int>(1,

    2, 3) val nums : MutableList<in Int> = mutableListOf<Number>(1.0, 2.0, 3.0)
  35. val nums : MutableList<out Number> = mutableListOf<Int>(1, 2, 3) val

    constructor = Nothing::class.java.getDeclaredConstructor() constructor.isAccessible = true val nothing = constructor.newInstance()
  36. val nums : MutableList<out Number> = mutableListOf<Int>(1, 2, 3) val

    constructor = Nothing::class.java.getDeclaredConstructor() constructor.isAccessible = true val nothing = constructor.newInstance() nums.add(nothing)
  37. val nums : MutableList<out Number> = mutableListOf<Int>(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]
  38. // List<out Any?> val list : List<*> = listOf(1, 2,

    3) // This is safe val foo : Any? = list[0]
  39. out

  40. class Foo<out T : Number>(val value : T) val foo

    : Foo<*> = Foo(1) // Foo<out Number>
  41. in

  42. class Foo<in T : Number> { fun foo(t : T)

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

    {} } val foo : Foo<*> = Foo<Number>() // Foo<in Nothing>
  44. class Foo<in T : Number> { fun foo(t : T)

    {} } val foo : Foo<*> = Foo<Number>() // Foo<in Nothing>
  45. class Foo<in T : Number> { fun foo(t : T)

    {} } val foo : Foo<*> = Foo<Number>() // Foo<in Nothing>
  46. class Foo<in T : Number> { fun foo(t : T)

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

    TODO() fun bar(t : T) {} }
  48. class Foo<T : Number> { fun foo() : T =

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

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

    TODO() fun bar(t : T) {} } val foo : Foo<*> = Foo<Int>() val n = foo.foo() // Foo<out Number> foo.bar(n) // Foo<in Nothing>
  51. 不変 共変 反変 <T> <out T> <in T> サブタイプを 引き継がない

    サブタイプを 引き継ぐ サブタイプが 逆転する Tは どこでも使用可 Tは 戻り値だけ Tは 引数だけ
  52. class Foo<T> Foo<*> // Foo<out Any?> : out position //

    Foo<in Nothing> : in position class Bar<T : Int> Bar<*> // Bar<out Int> : out position // Bar<in Nothing> : in position