Share
Embed
Kotlin Fest 2019: Kotlin型実践入門
KotlinではJavaにはない様々な型に関する機能が追加されたので、それらの解説
- Smart Casts
- Any、Unit、Nothing
- ジェネリクス
- Sealed class
- 関数型
Sato Shun
August 24, 2019
Transcript
189 slides
-
Kotlin Fest 2019 ࠤ౻ ൏ / Sato Shun Twitter: @stsn_jp
GitHub: satoshun Kotlinܕ࣮ફೖ -
Smart Casts • ifࣜɺwhenࣜɺisɺasͳͲͷ࣮ߦޙʹɺ໌ࣔతʹܕΩϟετ ͠ͳͯ͘ɺܕΛਪͯ͘͠ΕΔ • flow-sensitive typing (flow typing)ͱݺΕΔܕγεςϜ
• ͳܕΩϟετΛܰݮ͢Δ • ಈతܕ͚ݴޠͷμοΫλΠϐϯάͷΑ͏ͳॻ͖৺ • https://en.wikipedia.org/wiki/Flow-sensitive_typing -
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 -
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 -
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 -
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 -
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 -
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 -
if (hoge() && obj is Int) { a obj.toLong() }
a if (obj is String && obj is Int) { a obj.length obj.toLong() } a -
class Hoge { a private var obj: Any = "a"
fun test() { a if (obj is String) { a print((obj as String).length) } a } a } a -
class Hoge { a private var obj: Any = "a"
fun test() { a if (obj is String) { a print(obj.length) } a } a } a -
class Hoge { a private var obj: Any = "a"
fun test() { a if (obj is String) { a print(obj.length) } a } a } a ❌ -
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 -
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 -
val strs: List<String>? = … a if (!strs.isNullOrEmpty()) { a
println(strs!!.size) } a -
val strs: List<String>? = … a if (!strs.isNullOrEmpty()) { a
println(strs.size) } a -
public inline fun <T> Collection<T>?.isNullOrEmpty(): Boolean { a contract {
a returns(false) implies (this@isNullOrEmpty != null) } a return this == null || this.isEmpty() } a -
public inline fun <T> Collection<T>?.isNullOrEmpty(): Boolean { a contract {
a returns(false) implies (this@isNullOrEmpty != null) } a return this == null || this.isEmpty() } a -
public inline fun <T> Collection<T>?.isNullOrEmpty(): Boolean { a contract {
a returns(false) implies (this@isNullOrEmpty != null) } a return this == null || this.isEmpty() } a -
public inline fun <T> Collection<T>?.isNullOrEmpty(): Boolean { a contract {
a returns(false) implies (this@isNullOrEmpty != null) } a return this == null || this.isEmpty() } a -
val strs: List<String>? = … a if (!strs.isNullOrEmpty()) { a
println(strs!!.size) } a -
val strs: List<String>? = … a if (!strs.isNullOrEmpty()) { a
println(strs.size) } a -
fun assertTrue(actual: Boolean, message: String? = null) { a contract
{ returns() implies actual } a return asserter.assertTrue(message ?: "Expected value to be true.", actual) } a -
fun assertTrue(actual: Boolean, message: String? = null) { a contract
{ returns() implies actual } a return asserter.assertTrue(message ?: "Expected value to be true.", actual) } a -
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) -
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) -
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) -
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) -
public inline fun <R> run(block: () -> R): R {
a contract { a callsInPlace(block, InvocationKind.EXACTLY_ONCE) } a return block() } a -
public inline fun <R> run(block: () -> R): R {
a contract { a callsInPlace(block, InvocationKind.EXACTLY_ONCE) } a return block() } a -
public inline fun <R> 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 -
public inline fun <R> 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 -
fun checkObj(obj: Any?): Boolean { a return obj != null
} a if (checkObj(obj)) { a obj!!.javaClass } a -
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 -
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 -
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 -
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 -
@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 -
Anyܕ • JavaͷObjectͱҧ͏Ͳ͔͜ʁ • waitɺnotifyϝιου͕͑ͳ͍ • ໌ࣔతʹjava.lang.ObjectܕʹΩϟετ͢Εݺͼग़ͤΔ • getClassϝιου͕֦ுؔʹ •
public inline val <T : Any> T.javaClass: Class<T> • cloneɺfinalizeϝιου -
fun empty(): Unit { a } a val e =
empty() println(e) -
fun empty() { a } a val e = empty()
println(e) -
fun getName(): String { a return "name" } a fun
fail() { a throw RuntimeException() } a -
fun getName(): String { a return "name" } a fun
fail() { a throw RuntimeException() } a val name = if (isFriend()) { a getName() } a else { a fail() } a -
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 -
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 -
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) -
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) -
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) -
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) -
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) -
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) -
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) -
fun test(any: Any): String { a when (any) { a
is Int -> return "int" else -> fail() } a return "error" } a -
fun test(any: Any): String { a when (any) { a
is Int -> return "int" else -> fail() } a return "error" } a NothingܕͳͷͰɺ͜ͷݺͼग़͠ਖ਼ৗʹऴྃ͠ͳ͍ ͜ͷelseඞࣦͣഊ͢Δ -
fun test(any: Any): String { a when (any) { a
is Int -> return "int" else -> fail() } a } a -
// ඪ४ؔ public inline fun TODO(): Nothing = throw NotImplementedError()
// KotlinTest fun fail(msg: String): Nothing = throw Failures.failure(msg) -
// Kotlin/kotlinx.collections.immutable internal companion object { internal val EMPTY =
TrieNode<Nothing>(0, emptyArray()) } // airbnb/MvRx object Uninitialized : Async<Nothing>(complete = false, shouldLoad = true), Incomplete -
// kotlintest/kotlintest interface Show<in A> { a fun supports(a: Any?):
Boolean fun show(a: A): String } a object NullShow : Show<Nothing?> { a override fun supports(a: Any?): Boolean = a == null override fun show(a: Nothing?): String = "<null>" } a -
δΣωϦΫε • ࢄΞϊςʔγϣϯʢvariance annotationʣ • outɺinम০ࢠ • એݴଆมੑ: declaration-site variance
• where • reified • ֦ுؔ + δΣωϦΫε -
ࢄΞϊςʔγϣϯ • out - ڞม: covariance • in - ม:
contravariance • ࢦఆͳ͠: ෆม: invariance -
ڞมɺมɺෆม • Number <|- Intͷܧঝ͕ؔ͋Δ • A<Number> <|- A<Int>ͷ߹ɺAڞมͰ͋Δ •
A<Number> -|> A<Int>ͷ߹ɺAมͰ͋Δ -
ڞมɺมɺෆม • Number <|- Intͷܧঝ͕ؔ͋Δ • A<Number> <|- A<Int>ͷ߹ɺAڞมͰ͋Δ •
A<Number> -|> A<Int>ͷ߹ɺAมͰ͋Δ -
ڞมɺมɺෆม • Number <|- Intͷܧঝ͕ؔ͋Δ • A<Number> <|- A<Int>ͷ߹ɺAڞมͰ͋Δ •
A<Number> -|> A<Int>ͷ߹ɺAมͰ͋Δ • A<Number>ɺ A<Int>͕ؔͳ͍߹ɺAෆมͰ͋Δ -
ڞมɺมɺෆม • Number <|- Intͷܧঝ͕ؔ͋Δ • A<Number> <|- A<Int>ͷ߹ɺAڞมͰ͋Δ •
A<Number> -|> A<Int>ͷ߹ɺAมͰ͋Δ • A<Number>ɺ A<Int>͕ؔͳ͍߹ɺAෆมͰ͋Δ -
// ڞม val a: A<Int> = A<Int>() a val b:
A<Number> = a -
// ڞม val a: A<Int> = A<Int>() a val b:
A<Number> = a // ม val a: A<Number> = A<Number>() a val b: A<Int> = a -
// ڞม val a: A<Int> = A<Int>() a val b:
A<Number> = a // ม val a: A<Number> = A<Number>() a val b: A<Int> = a // ෆม val a: A<Int> = A<Int>() a -
interface Mapper<T> { a fun map(s: String): T } a
class IntMapper : Mapper<Int> { a override fun map(s: String): Int = s.toInt() } a -
interface Mapper<T> { a fun map(s: String): T } a
class IntMapper : Mapper<Int> { a override fun map(s: String): Int = s.toInt() } a fun hoge(mapper: Mapper<Number>) { a mapper.map("10") } a -
interface Mapper<T> { a fun map(s: String): T } a
class IntMapper : Mapper<Int> { a override fun map(s: String): Int = s.toInt() } a fun hoge(mapper: Mapper<Number>) { a mapper.map("10") } a val mapper = IntMapper() hoge(mapper) -
interface Mapper<T> { a fun map(s: String): T } a
class IntMapper : Mapper<Int> { a override fun map(s: String): Int = s.toInt() } a fun hoge(mapper: Mapper<Number>) { a mapper.map("10") } a val mapper = IntMapper() hoge(mapper) ❌ -
interface Mapper<T> { a fun map(s: String): T } a
class IntMapper : Mapper<Int> { a override fun map(s: String): Int = s.toInt() } a fun hoge(mapper: Mapper<Number>) { a mapper.map("10") } a val mapper = IntMapper() hoge(mapper) ❌ -
interface Mapper<out T> { a fun map(s: String): T }
a class IntMapper : Mapper<Int> { a override fun map(s: String): Int = s.toInt() } a fun hoge(mapper: Mapper<Number>) { a mapper.map("10") } a val mapper = IntMapper() hoge(mapper) ❌ -
interface Mapper<out T> { a fun map(s: String): T }
a class IntMapper : Mapper<Int> { a override fun map(s: String): Int = s.toInt() } a fun hoge(mapper: Mapper<Number>) { a mapper.map("10") } a val mapper = IntMapper() hoge(mapper) ❌ -
interface Mapper<out T> { a fun map(s: String): T }
a class IntMapper : Mapper<Int> { a override fun map(s: String): Int = s.toInt() } a fun hoge(mapper: Mapper<Number>) { a mapper.map("10") } a val mapper = IntMapper() hoge(mapper) -
ListͱMutableList public interface List<out E> : Collection<E> public interface MutableList<E>
: List<E>, … • Listoutम০ࢠ͕͍͍ͯΔͷͰɺڞม • MutableListԿ͍͍ͯͳ͍ͷͰɺෆม -
val strs: List<String> = listOf("a", “b") val anys: List<Any> =
strs val a: Any = anys[0] -
val strs: List<String> = listOf("a", “b") val anys: List<Any> =
strs val a: Any = anys[0] val a2: Any? = anys2.getOrNull(1) -
val strs: List<String> = listOf("a", “b") val anys: List<Any> =
strs val a: Any = anys[0] val a2: Any? = anys2.getOrNull(1) -
val strs: MutableList<String> = mutableListOf("a", "b") val anys: MutableList<Any> =
strs anys.add(10) val str: String = strs.last() -
val strs: MutableList<String> = mutableListOf("a", "b") val anys: MutableList<Any> =
strs anys.add(10) val str: String = strs.last() ❌ -
val strs: MutableList<String> = mutableListOf("a", "b") val anys: MutableList<Any> =
strs anys.add(10) val str: String = strs.last() -
PECS • Producer Extends Consumer Super • Producerreadͷੑ࣭Λ࣋ͭ • Consumerwriteͷੑ࣭Λ࣋ͭ
• ListProducerͷੑ࣭ͷΈΛ࣋ͭͷͰɺExtends = out ڞมʹ ग़དྷΔ • MutableListProducerͱConsumerͷੑ࣭Λ࣋ͭͷͰɺෆม -
2ͭҎ্ͷ্քΛ࣋ͭܕม • 1ͭͷ্քʢupper boundʣΛ࣋ͭͱ͖ɺׅހʹॻ͚ྑ ͍ • fun <T : CharSequence>
hoge(t: T) {…} • 2ͭҎ্ͷ্քΛ࣋ͭ߹Ͳ͏͢ΕΑ͍͔ʁ • ྫ͑ɺActivity͔ͭOnClickListenerΛ࣋ͭܕΛड͚ೖΕΔܕ มΛఆ͍ٛͨ͠ -
class OnClickActivity() : Activity(), OnClickListener fun setClick(activity: OnClickActivity) { a
} a val activity = OnClickActivity() setClick(activity) -
class OnClickActivity() : Activity(), OnClickListener fun setClick(activity: OnClickActivity) { a
} a val activity = OnClickActivity() setClick(activity) class OnClickActivity2() : Activity(), OnClickListener -
class OnClickActivity() : Activity(), OnClickListener fun setClick(activity: OnClickActivity) { a
} a val activity = OnClickActivity() setClick(activity) class OnClickActivity2() : Activity(), OnClickListener val activity2 = OnClickActivity2() setClick(activity2) -
class OnClickActivity() : Activity(), OnClickListener fun setClick(activity: OnClickActivity) { a
} a val activity = OnClickActivity() setClick(activity) class OnClickActivity2() : Activity(), OnClickListener val activity2 = OnClickActivity2() setClick(activity2) ❌ -
fun <T> setClick(activity: T) where T : Activity, T :
OnClickListener { a } a -
fun <T> setClick(activity: T) where T : Activity, T :
OnClickListener { a } a val activity = OnClickActivity() setClick(activity) -
fun <T> setClick(activity: T) where T : Activity, T :
OnClickListener { } val activity = OnClickActivity() setClick(activity) val activity2 = OnClickActivity2() setClick(activity2) -
internal abstract class NIOSocketImpl<out S>( override val channel: S, val
selector: SelectorManager, val pool: ObjectPool<ByteBuffer>? ) : ReadWriteSocket, SelectableBase(channel), CoroutineScope where S : java.nio.channels.ByteChannel, S : java.nio.channels.SelectableChannel Ktor -
internal abstract class NIOSocketImpl<out S>( override val channel: S, val
selector: SelectorManager, val pool: ObjectPool<ByteBuffer>? ) : ReadWriteSocket, SelectableBase(channel), CoroutineScope where S : java.nio.channels.ByteChannel, S : java.nio.channels.SelectableChannel Ktor -
internal abstract class NIOSocketImpl<out S>( override val channel: S, val
selector: SelectorManager, val pool: ObjectPool<ByteBuffer>? ) : 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<DatagramChannel>(channel, selector, DefaultDatagramByteBufferPool) Ktor -
internal abstract class NIOSocketImpl<out S>( override val channel: S, val
selector: SelectorManager, val pool: ObjectPool<ByteBuffer>? ) : 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<DatagramChannel>(channel, selector, DefaultDatagramByteBufferPool) internal class SocketImpl<out S : SocketChannel>( override val channel: S, private val socket: java.net.Socket, selector: SelectorManager ) : NIOSocketImpl<S>(channel, selector, pool = null), Socket Ktor -
inline fun <reified T> hoge(obj: Any) { a println(T::class.java) a
if (obj is T) { a println("obj is T") a } a } a -
inline fun <reified T> hoge(obj: Any) { a println(T::class.java) a
if (obj is T) { a println("obj is T") a } a } a -
inline fun <reified T> hoge(obj: Any) { a println(T::class.java) a
if (obj is T) { a println("obj is T") a } a } a -
class A<T>(val value: T) { a fun isNull(): Boolean {
a return value != null } a } a -
class A<T>(val value: T) { a fun isNull(): Boolean {
a return value != null } a } a val a1: A<Int?> = A(null) a a1.isNull() a -
class A<T>(val value: T) { a fun isNull(): Boolean {
a return value != null } a } a val a1: A<Int?> = A(null) a a1.isNull() a val a2: A<Int> = A(10) a a2.isNull() a -
class A<T>(val value: T) a fun <T : Any> A<T?>.isNull():
Boolean { a return value != null a } a val a1: A<Int?> = A(null) a a1.isNull() a val a2: A<Int> = A(10) a a2.isNull() a -
class A<T>(val value: T) a fun <T : Any> A<T?>.isNull():
Boolean { a return value != null a } a val a1: A<Int?> = A(null) a a1.isNull() a val a2: A<Int> = A(10) a a2.isNull() a -
class A<T>(val value: T) a fun <T : Any> A<T?>.isNull():
Boolean { a return value != null a } a val a1: A<Int?> = A(null) a a1.isNull() a val a2: A<Int> = A(10) a a2.isNull() a -
class A<T>(val value: T) a fun <T : Any> A<T?>.isNull():
Boolean { a return value != null a } a val a1: A<Int?> = A(null) a a1.isNull() a val a2: A<Int> = A(10) a a2.isNull() a ❌ -
abstract class Either object Left : Either() object Right :
Either() when (obj) { a Left -> println("is Left") Right -> println("is Right") else -> println("else") } a -
sealed class Either object Left : Either() object Right :
Either() when (obj) { a Left -> println("is Left") Right -> println("is Right") else -> println("else") } a -
sealed class Either object Left : Either() object Right :
Either() when (obj) { a Left -> println("is Left") Right -> println("is Right") } a -
public abstract class Either { private Either() { } //
$FF: synthetic method public Either(DefaultConstructorMarker $constructor_marker) { this(); } } -
public abstract class Either { private Either() { } //
$FF: synthetic method public Either(DefaultConstructorMarker $constructor_marker) { this(); } } -
fun hoge(body: (Int) -> String) { a body(10) } a
hoge { it.toString() } a -
fun add(a1: Int, a2: Int): Int { a return a1
+ a2 } a add add(10, 20) -
fun add(a1: Int, a2: Int): Int { a return a1
+ a2 } a add add(10, 20) val a: (Int, Int) -> Int = ::add -
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) -
} a add add(10, 20) val a: (Int, Int) ->
Int = ::add a(10, 20) fun <P1, P2, R> ((P1, P2) -> R).curried(): (P1) -> (P2) -> R = { p1: P1 -> { p2: P2 -> this(p1, p2) } } a -
} a add add(10, 20) val a: (Int, Int) ->
Int = ::add a(10, 20) fun <P1, P2, R> ((P1, P2) -> R).curried(): (P1) -> (P2) -> R = { p1: P1 -> { p2: P2 -> this(p1, p2) } } a -
} a add add(10, 20) val a: (Int, Int) ->
Int = ::add a(10, 20) fun <P1, P2, R> ((P1, P2) -> R).curried(): (P1) -> (P2) -> R = { p1: P1 -> { p2: P2 -> this(p1, p2) } } a -
} a add add(10, 20) val a: (Int, Int) ->
Int = ::add a(10, 20) fun <P1, P2, R> ((P1, P2) -> R).curried(): (P1) -> (P2) -> R = { p1: P1 -> { p2: P2 -> this(p1, p2) } } a val curried = a.curried() -
} a add add(10, 20) val a: (Int, Int) ->
Int = ::add a(10, 20) fun <P1, P2, R> ((P1, P2) -> R).curried(): (P1) -> (P2) -> R = { p1: P1 -> { p2: P2 -> this(p1, p2) } } a val curried = a.curried() curried(10)(20) -
class A : (Int) -> Unit { a override fun
invoke(p1: Int) { a println("call $p1") } a } a val a = A() a.invoke(10) -
class A : (Int) -> Unit { a override fun
invoke(p1: Int) { a println("call $p1") } a } a val a = A() a(10) -
public interface Function1<in P1, out R> : Function<R> { public
operator fun invoke(p1: P1): R } a -
public interface Function1<in P1, out R> : Function<R> { public
operator fun invoke(p1: P1): R } a val a: (Number) -> Number = { it } a -
public interface Function1<in P1, out R> : Function<R> { public
operator fun invoke(p1: P1): R } a val a: (Number) -> Number = { it } a val a1: (Int) -> Number = a -
public interface Function1<in P1, out R> : Function<R> { public
operator fun invoke(p1: P1): R } a val a: (Number) -> Number = { it } a val a1: (Int) -> Number = a -
public interface Function1<in P1, out R> : Function<R> { public
operator fun invoke(p1: P1): R } a val a: (Number) -> Number = { it } a val a1: (Int) -> Number = a val a2: (Number) -> Any = a -
public interface Function1<in P1, out R> : Function<R> { public
operator fun invoke(p1: P1): R } a val a: (Number) -> Number = { it } as val a1: (Int) -> Number = a val a2: (Number) -> Any = a -
SAMม • SAM? • Single Abstract Method • 1ͭͷநϝιουΛ࣋ͭ •
Kotlin͔ΒJavaఆٛͷSAMΛ͏ͱ͖ʹɺϥϜμࣜͰ؆ܿʹ ॻ͘͜ͱ͕ग़དྷΔ -
public class SamTest { a public static void foo(Runnable a,
Runnable b) { a } a } a fun test() { a SamTest.foo({}) { a } a } a -
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(); } -
public class SamTest { a public static void foo(Runnable a,
Runnable b) { a } a } a fun test(r: Runnable) { a SamTest.foo(r) { } } a -
public class SamTest { a public static void foo(Runnable a,
Runnable b) { a } a } a fun test(r: Runnable) { a SamTest.foo(r) { } } a ❌ -
// RxJava val o1 = Observable.just(1) val o2 = Observable.just(2)
val combination = Observable .combineLatest(o1, o2, { n1, n2 -> n1 to n2 }) a -
// RxJava val o1 = Observable.just(1) val o2 = Observable.just(2)
val combination = Observable .combineLatest(o1, o2, { n1, n2 -> n1 to n2 }) public static <T1, T2, R> Observable<R> combineLatest( ObservableSource<? extends T1> source1, ObservableSource<? extends T2> source2, BiFunction<? super T1, ? super T2, ? extends R> combiner ) a -
// RxJava val o1 = Observable.just(1) val o2 = Observable.just(2)
val combination = Observable .combineLatest(o1, o2, { n1, n2 -> n1 to n2 }) public static <T1, T2, R> Observable<R> combineLatest( ObservableSource<? extends T1> source1, ObservableSource<? extends T2> source2, BiFunction<? super T1, ? super T2, ? extends R> combiner ) a public interface ObservableSource<T> { a void subscribe(@NonNull Observer<? super T> observer); } ˇ -
// RxJava val o1 = Observable.just(1) val o2 = Observable.just(2)
val combination = Observable .combineLatest(o1, o2, { n1, n2 -> n1 to n2 }) -
// RxJava val o1 = Observable.just(1) val o2 = Observable.just(2)
val combination = Observable .combineLatest(o1, o2, { n1, n2 -> n1 to n2 }) ❌ -
// RxJava val o1 = Observable.just(1) val o2 = Observable.just(2)
val combination = Observable .combineLatest(o1, o2, BiFunction { n1, n2 -> n1 to n2 }) -
public static <T1, T2, R> Observable<R> combineLatest( ObservableSource<? extends T1>
source1, ObservableSource<? extends T2> source2, BiFunction<? super T1, ? super T2, ? extends R> combiner ) a -
public static <T1, T2, R> Observable<R> combineLatest( Observable<? extends T1>
source1, Observable<? extends T2> source2, BiFunction<? super T1, ? super T2, ? extends R> combiner ) a -
public static <T1, T2, R> Observable<R> 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 }) -
public static <T1, T2, R> Observable<R> 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 }) -
·ͱΊ • KotlinͷSmart CastsͱܕਪͰɺͳίʔυΛݮΒ͠ɺҰ ෦μοΫλΠϐϯάͷΑ͏ͳॻ͖৺ΛಘΔ͜ͱ͕Մೳʂ • ॊೈͳδΣωϦΫεAPIΛ͏͜ͱͰɺॊೈͳAPI͕ߏஙग़དྷ Δʂ • NothingܕΛ͏͜ͱͰɺॊೈͳAPIΛߏஙͰ͖Δʂ
• Sealed classΛ͏͜ͱͰɺॊೈͳAPIΛߏஙͰ͖Δʂ -
Kotlin Fest 2019 ࠤ౻ ൏ / Sato Shun Twitter: @stsn_jp
GitHub: satoshun Kotlinܕ࣮ફೖ