Slide 1

Slide 1 text

Kotlin Fest 2019 ࠤ౻ ൏ / Sato Shun Twitter: @stsn_jp GitHub: satoshun Kotlinܕ࣮ફೖ໳

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

Smart Casts • ifࣜɺwhenࣜɺisɺasͳͲͷ࣮ߦޙʹɺ໌ࣔతʹܕΩϟετ ͠ͳͯ͘΋ɺܕΛਪ࿦ͯ͘͠ΕΔ • flow-sensitive typing (flow typing)ͱݺ͹ΕΔܕγεςϜ • ৑௕ͳܕΩϟετΛܰݮ͢Δ • ಈతܕ෇͚ݴޠͷμοΫλΠϐϯάͷΑ͏ͳॻ͖৺஍ • https://en.wikipedia.org/wiki/Flow-sensitive_typing

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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)

Slide 31

Slide 31 text

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)

Slide 32

Slide 32 text

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)

Slide 33

Slide 33 text

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)

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

@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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

val s = "" s.notify()

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

fun empty() { a } a empty()

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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)

Slide 60

Slide 60 text

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)

Slide 61

Slide 61 text

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)

Slide 62

Slide 62 text

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)

Slide 63

Slide 63 text

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)

Slide 64

Slide 64 text

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)

Slide 65

Slide 65 text

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)

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

// 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

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

෼ࢄΞϊςʔγϣϯ • out - ڞม: covariance • in - ൓ม: contravariance • ࢦఆͳ͠: ෆม: invariance

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

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)

Slide 91

Slide 91 text

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) ❌

Slide 92

Slide 92 text

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) ❌

Slide 93

Slide 93 text

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) ❌

Slide 94

Slide 94 text

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) ❌

Slide 95

Slide 95 text

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)

Slide 96

Slide 96 text

ListͱMutableList public interface List : Collection public interface MutableList : List, …

Slide 97

Slide 97 text

ListͱMutableList public interface List : Collection public interface MutableList : List, … • List͸outम০ࢠ͕෇͍͍ͯΔͷͰɺڞม • MutableList͸Կ΋෇͍͍ͯͳ͍ͷͰɺෆม

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

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

Slide 102

Slide 102 text

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

Slide 103

Slide 103 text

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

Slide 104

Slide 104 text

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

Slide 105

Slide 105 text

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

Slide 106

Slide 106 text

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

Slide 107

Slide 107 text

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

Slide 108

Slide 108 text

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

Slide 109

Slide 109 text

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

Slide 110

Slide 110 text

PECS • Producer Extends Consumer Super • Producer͸readͷੑ࣭Λ࣋ͭ • Consumer͸writeͷੑ࣭Λ࣋ͭ • List͸Producerͷੑ࣭ͷΈΛ࣋ͭͷͰɺExtends = out ڞมʹ ग़དྷΔ • MutableList͸ProducerͱConsumerͷੑ࣭Λ࣋ͭͷͰɺෆม

Slide 111

Slide 111 text

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

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

2ͭҎ্ͷ্քΛ࣋ͭܕม਺ • 1ͭͷ্քʢupper boundʣΛ࣋ͭͱ͖͸ɺׅހ಺ʹॻ͚͹ྑ ͍ • fun hoge(t: T) {…} • 2ͭҎ্ͷ্քΛ࣋ͭ৔߹͸Ͳ͏͢Ε͹Α͍͔ʁ • ྫ͑͹ɺActivity͔ͭOnClickListenerΛ࣋ͭܕΛड͚ೖΕΔܕ ม਺Λఆ͍ٛͨ͠

Slide 114

Slide 114 text

class OnClickActivity() : Activity(), OnClickListener

Slide 115

Slide 115 text

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

Slide 116

Slide 116 text

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

Slide 117

Slide 117 text

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

Slide 118

Slide 118 text

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

Slide 119

Slide 119 text

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

Slide 120

Slide 120 text

fun setClick(activity: OnClickActivity) { a } a

Slide 121

Slide 121 text

fun setClick(activity: T)

Slide 122

Slide 122 text

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

Slide 123

Slide 123 text

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

Slide 124

Slide 124 text

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

Slide 125

Slide 125 text

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

Slide 126

Slide 126 text

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

Slide 127

Slide 127 text

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

Slide 128

Slide 128 text

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

Slide 129

Slide 129 text

reified • ؔ਺಺͔Βܕม਺ʹΞΫηεग़དྷΔ • JavaͰ͸ܕม਺ʹϥϯλΠϜ࣌ʹΞΫηεͰ͖ͳ͍ • Type Erasureͱݺ͹ΕΔݴޠ࢓༷ͷͨΊɺίϯύΠϧޙʹܕม਺͕ ࡟আ͞ΕΔͨΊ

Slide 130

Slide 130 text

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

Slide 131

Slide 131 text

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

Slide 132

Slide 132 text

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

Slide 133

Slide 133 text

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

Slide 134

Slide 134 text

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

Slide 135

Slide 135 text

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

Slide 136

Slide 136 text

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

Slide 137

Slide 137 text

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

Slide 138

Slide 138 text

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

Slide 139

Slide 139 text

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

Slide 140

Slide 140 text

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 ❌

Slide 141

Slide 141 text

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

Slide 142

Slide 142 text

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

Slide 143

Slide 143 text

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

Slide 144

Slide 144 text

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

Slide 145

Slide 145 text

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

Slide 146

Slide 146 text

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

Slide 147

Slide 147 text

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

Slide 148

Slide 148 text

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

Slide 149

Slide 149 text

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

Slide 150

Slide 150 text

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

Slide 151

Slide 151 text

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

Slide 152

Slide 152 text

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

Slide 153

Slide 153 text

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

Slide 154

Slide 154 text

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

Slide 155

Slide 155 text

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

Slide 156

Slide 156 text

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

Slide 157

Slide 157 text

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)

Slide 158

Slide 158 text

} 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

Slide 159

Slide 159 text

} 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

Slide 160

Slide 160 text

} 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

Slide 161

Slide 161 text

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

Slide 162

Slide 162 text

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

Slide 163

Slide 163 text

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

Slide 164

Slide 164 text

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

Slide 165

Slide 165 text

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

Slide 166

Slide 166 text

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

Slide 167

Slide 167 text

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

Slide 168

Slide 168 text

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

Slide 169

Slide 169 text

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

Slide 170

Slide 170 text

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

Slide 171

Slide 171 text

SAMม׵ • SAM? • Single Abstract Method • 1ͭͷந৅ϝιουΛ࣋ͭ • Kotlin͔ΒJavaఆٛͷSAMΛ࢖͏ͱ͖ʹɺϥϜμࣜͰ؆ܿʹ ॻ͘͜ͱ͕ग़དྷΔ

Slide 172

Slide 172 text

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

Slide 173

Slide 173 text

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

Slide 174

Slide 174 text

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

Slide 175

Slide 175 text

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

Slide 176

Slide 176 text

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

Slide 177

Slide 177 text

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

Slide 178

Slide 178 text

// 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

Slide 179

Slide 179 text

// 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); } ˇ

Slide 180

Slide 180 text

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

Slide 181

Slide 181 text

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

Slide 182

Slide 182 text

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

Slide 183

Slide 183 text

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

Slide 184

Slide 184 text

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

Slide 185

Slide 185 text

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

Slide 186

Slide 186 text

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

Slide 187

Slide 187 text

NewInference • kotlinͰ͸SAMม׵ͷ໰୊ʹରͯ͠ɺ৽͍͠ܕਪ࿦Λ։ൃͯ͠ ͍Δ • ݱࡏɺexperimentalͷཱͪҐஔ͕ͩɺઃఆͰenableʹ͢Δ͜ͱ ͕Մೳ

Slide 188

Slide 188 text

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

Slide 189

Slide 189 text

Kotlin Fest 2019 ࠤ౻ ൏ / Sato Shun Twitter: @stsn_jp GitHub: satoshun Kotlinܕ࣮ફೖ໳