Slide 1

Slide 1 text

Hiroyuki Mori @moridroid Kotlinもう一歩

Slide 2

Slide 2 text

本書きました!

Slide 3

Slide 3 text

goo.gl/fW2YPh

Slide 4

Slide 4 text

Kotlinもう一歩

Slide 5

Slide 5 text

Kotlinのタイプシステム

Slide 6

Slide 6 text

クラスとタイプ

Slide 7

Slide 7 text

クラス ≠ タイプ

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

タイプとは何か

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

だから安全!

Slide 16

Slide 16 text

タイプとサブタイプ

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

クイズ

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

In Kotlin in Action

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

Any

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

Nothing

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

nullableとnon-null

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

No content

Slide 46

Slide 46 text

まとめ

Slide 47

Slide 47 text

No content

Slide 48

Slide 48 text

Generics

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

上限境界

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

型引数とnullability

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

Type Erasure

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

変位

Slide 66

Slide 66 text

Int <: Number

Slide 67

Slide 67 text

Int <: Number val number : Number = 123

Slide 68

Slide 68 text

Int <: Number List <: List

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

Int <: Number List <: List MutableList <: MutableList

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

invariant, covariant, contravariant  不変   共変    反変   

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

inとout

Slide 92

Slide 92 text

out

Slide 93

Slide 93 text

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

Slide 94

Slide 94 text

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

Slide 95

Slide 95 text

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

Slide 96

Slide 96 text

public interface List : Collection {

Slide 97

Slide 97 text

in

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

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

Slide 102

Slide 102 text

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

Slide 103

Slide 103 text

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

Slide 104

Slide 104 text

Type Projection

Slide 105

Slide 105 text

MutableList <: MutableList

Slide 106

Slide 106 text

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

Slide 107

Slide 107 text

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

Slide 108

Slide 108 text

class Foo val foo : Foo class Bar val bar : Bar

Slide 109

Slide 109 text

余談

Slide 110

Slide 110 text

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

Slide 111

Slide 111 text

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

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

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]

Slide 114

Slide 114 text

Star Projection

Slide 115

Slide 115 text

// Java Way List> list;

Slide 116

Slide 116 text

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

Slide 117

Slide 117 text

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

Slide 118

Slide 118 text

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

Slide 119

Slide 119 text

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

Slide 120

Slide 120 text

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

Slide 121

Slide 121 text

out

Slide 122

Slide 122 text

class Foo(val value : T)

Slide 123

Slide 123 text

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

Slide 124

Slide 124 text

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

Slide 125

Slide 125 text

in

Slide 126

Slide 126 text

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

Slide 127

Slide 127 text

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

Slide 128

Slide 128 text

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

Slide 129

Slide 129 text

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

Slide 130

Slide 130 text

No content

Slide 131

Slide 131 text

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

Slide 132

Slide 132 text

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

Slide 133

Slide 133 text

invariant

Slide 134

Slide 134 text

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

Slide 135

Slide 135 text

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

Slide 136

Slide 136 text

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

Slide 137

Slide 137 text

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

Slide 138

Slide 138 text

まとめ

Slide 139

Slide 139 text

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

Slide 140

Slide 140 text

class Foo Foo<*> // Foo class Bar Bar<*> // Bar

Slide 141

Slide 141 text

class Foo Foo<*> // Foo class Bar Bar<*> // Bar

Slide 142

Slide 142 text

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

Slide 143

Slide 143 text

Hiroyuki Mori @moridroid Thank you