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

広く浅く語るKotlinの魅力

 広く浅く語るKotlinの魅力

https://kotlin.connpass.com/event/61903/ で使用したスライドです。

Taro Nagasawa

July 25, 2017
Tweet

More Decks by Taro Nagasawa

Other Decks in Programming

Transcript

  1. (事実上の)Kotlinエバンジェリスト • 日本Kotlinユーザグループ代表 • 講演実績 ◦ DroidKaigi 2015, 2016, 2017

    ◦ JJUG CCC 2015 Fall ◦ Hacker Tackle 2016 ◦ Lightweight Language of Things など • 執筆実績 ◦ Kotlinスタートブック ◦ 日経ソフトウエア ◦ Software Design ◦ I/O など
  2. Q. Kotlinとは? A. プログラミング言語のひとつ • 静的型付けオブジェクト指向言語 • いわゆる「JVM言語」 • 開発元:

    JetBrains • 2016年2月に正式リリース • Apache License ver2.0 静的型付け: プログラムの実行前(コンパイル時)に型が決まる オブジェクト指向: Javaと同じく対象物(オブジェクト)に着目してプログラ ムを組み上げる
  3. Q. Kotlinとは? A. プログラミング言語のひとつ • 静的型付けオブジェクト指向言語 • いわゆる「JVM言語」 • 開発元:

    JetBrains • 2016年2月に正式リリース • Apache License ver2.0 Java仮想マシン(JVM)の上で動作する「Javaバイトコード」 にコンパイルされるようなプログラミング言語 JavaScriptやLLVMもターゲットに!?
  4. Q. Kotlinとは? A. プログラミング言語のひとつ • 静的型付けオブジェクト指向言語 • いわゆる「JVM言語」 • 開発元:

    JetBrains • 2016年2月に正式リリース • Apache License ver2.0 統合開発環境 IntelliJ IDEAの開発元の会社。 Googleと共同で財団の設立。 大きな後ろ盾があることを意味する。
  5. Q. Kotlinとは? A. プログラミング言語のひとつ • 静的型付けオブジェクト指向言語 • いわゆる「JVM言語」 • 開発元:

    JetBrains • 2016年2月に正式リリース • Apache License ver2.0 新しい言語です!現在 ver1.1.3-2
  6. Q. Kotlinとは? A. プログラミング言語のひとつ • 静的型付けオブジェクト指向言語 • いわゆる「JVM言語」 • 開発元:

    JetBrains • 2016年2月に正式リリース • Apache License ver2.0 オープンソースです。 ソースコードを自由に入手・改造できる!
  7. Q. JVM言語? A. JVMサイコーだけどJava言語はチョット... • 冗長、ボイラープレートの嵐 • nullポインタのデリファレンス問題 • 後方互換性の維持

    ◦ 古い文法が存在する ◦ 型安全性に問題あり いろんなところで動いている。 JVM用コード(Javaコード)がたくさんある。 歴史長い。強い。
  8. Q. JVM言語? A. JVMサイコーだけどJava言語はチョット... • 冗長、ボイラープレートの嵐 • nullポインタのデリファレンス問題 • 後方互換性の維持

    ◦ 古い文法が存在する ◦ 型安全性に問題あり めっちゃバグるんですけど。 そもそもの言語仕様がアレなのでは。
  9. Q. JVM言語? A. JVMサイコーだけどJava言語はチョット... • 冗長、ボイラープレートの嵐 • nullポインタのデリファレンス問題 • 後方互換性の維持

    ◦ 古い文法が存在する ◦ 型安全性に問題あり 今は使うべきでない文法が存在する。 削除してくれればいいのに...そういうわけにも。
  10. 拡張プロパティ val Int.isEven: Boolean get() = this % 2 ==

    0 123.isEven //=> false Intに対する 拡張プロパティ
  11. プロパティの例 class Name { var value: String = "" get()

    = field set(newValue) { field = newValue } val length: Int get() = value.length } name.value = "Taro" name.length //=> 4
  12. プロパティの例 class Name { var value: String = "" get()

    = field set(newValue) { field = newValue } val length: Int get() = value.length } name.value = "Taro" name.length //=> 4 変更可能な プロパティvalue 変更不可能な プロパティlength こんな感じで使える
  13. プロパティの例 class Name { var value: String = "" get()

    = field set(newValue) { field = newValue } val length: Int get() = value.length } name.value = "Taro" name.length //=> 4 取得時の実装 取得時の実装 セット時の実装
  14. プロパティの例 class Name { var value: String = "" get()

    = field set(newValue) { field = newValue } val length: Int get() = value.length } name.value = "Taro" name.length //=> 4 暗黙の変数 field 暗黙の変数 field 初期値必須
  15. プロパティの例 class Name { var value: String = "" get()

    = field set(newValue) { field = newValue } val length: Int get() = value.length } name.value = "Taro" name.length //=> 4 省略OK
  16. データクラスが提供する便利なメソッド val taro = Person(id=5, name="Taro") taro.toString() //=> Person(id=5, name=Taro)

    taro == Person(id=5, name="Taro") //=> true val jiro = taro.copy(name="Jiro") val (id, name) = jiro id //=> 5 name //=> Jiro
  17. データクラスが提供する便利なメソッド val taro = Person(id=5, name="Taro") taro.toString() //=> Person(id=5, name=Taro)

    taro == Person(id=5, name="Taro") //=> true val jiro = taro.copy(name="Jiro") val (id, name) = jiro id //=> 5 name //=> Jiro 名前付き引数
  18. データクラスが提供する便利なメソッド val taro = Person(id=5, name="Taro") taro.toString() //=> Person(id=5, name=Taro)

    taro == Person(id=5, name="Taro") //=> true val jiro = taro.copy(name="Jiro") val (id, name) = jiro id //=> 5 name //=> Jiro toStringメソッドの実装が自動生成される
  19. データクラスが提供する便利なメソッド val taro = Person(id=5, name="Taro") taro.toString() //=> Person(id=5, name=Taro)

    taro == Person(id=5, name="Taro") //=> true val jiro = taro.copy(name="Jiro") val (id, name) = jiro id //=> 5 name //=> Jiro equalsメソッドの実装が自動生成される
  20. データクラスが提供する便利なメソッド val taro = Person(id=5, name="Taro") taro.toString() //=> Person(id=5, name=Taro)

    taro == Person(id=5, name="Taro") //=> true val jiro = taro.copy(name="Jiro") val (id, name) = jiro id //=> 5 name //=> Jiro コピーメソッド
  21. データクラスが提供する便利なメソッド val taro = Person(id=5, name="Taro") taro.toString() //=> Person(id=5, name=Taro)

    taro == Person(id=5, name="Taro") //=> true val jiro = taro.copy(name="Jiro") val (id, name) = jiro id //=> 5 name //=> Jiro 中身を分解して取得可能
  22. 安全呼び出し s?.length if (s != null) s.length else null 同じ

    if-elseは式 (評価されて値になる)
  23. 安全呼び出し s?.length if (s != null) s.length else null 同じ

    if-elseは式 (評価されて値になる) foo?.bar()?.baz()?.qux() メソッドチェーンで役立つ
  24. 拡張関数 let fun <T, R> T.let(f: (T)->R): R = f(this)

    • 任意の型Tの拡張関数 • 戻り値の型は、任意の型R
  25. 拡張関数 let fun <T, R> T.let(f: (T)->R): R = f(this)

    • 任意の型Tの拡張関数 • 戻り値の型は、任意の型R • 引数fは「Tを引数に取ってRを返す」関数
  26. 拡張関数 let fun <T, R> T.let(f: (T)->R): R = f(this)

    • 任意の型Tの拡張関数 • 戻り値の型は、任意の型R • 引数fは「Tを引数に取ってRを返す」関数 • 引数としてthisを渡してfを呼び出し、その戻り値をそのまま 返す
  27. 拡張関数 let fun <T, R> T.let(f: (T)->R): R = f(this)

    • 任意の型Tの拡張関数 • 戻り値の型は、任意の型R • 引数fは「Tを引数に取ってRを返す」関数 • 引数としてthisを渡してfを呼び出し、その戻り値をそのまま 返す val got = "I love Kotlin".let { s -> s.toLowerCase() } got //=> "i love kotlin"
  28. 拡張関数 let fun <T, R> T.let(f: (T)->R): R = f(this)

    • 任意の型Tの拡張関数 • 戻り値の型は、任意の型R • 引数fは「Tを引数に取ってRを返す」関数 • 引数としてthisを渡してfを呼び出し、その戻り値をそのまま 返す val got = "I love Kotlin".let { s -> s.toLowerCase() } got //=> "i love kotlin" ラムダ式を渡す
  29. 拡張関数 let fun <T, R> T.let(f: (T)->R): R = f(this)

    • 任意の型Tの拡張関数 • 戻り値の型は、任意の型R • 引数fは「Tを引数に取ってRを返す」関数 • 引数としてthisを渡してfを呼び出し、その戻り値をそのまま 返す val got = "I love Kotlin".let { s -> s.toLowerCase() } got //=> "i love kotlin"
  30. 安全呼び出し + 拡張関数let val messag: String? = getMessage() val got:

    String = message?.let { s -> s.toLowerCase() } messageがnullだったら これ以降の呼び出しは行われない
  31. 安全呼び出し + 拡張関数let val messag: String? = getMessage() val got:

    String = message?.let { s -> s.toLowerCase() } messageがnullでなければ この中が実行される
  32. 複数のNullableをNotNullに→素直にifで if (foo != null && bar != null) {

    foo.execute(bar) } foo?.let { f -> bar?.let { b -> f.execute(b) } } ◎よい例 ✖ダメな例(必要以上にネストが深くなる)
  33. Nullableに関する演算子 val a: String = b ?: "default" val a:

    String = b!! エルビス演算子 !!演算子
  34. Nullableに関する演算子 val a: String = b ?: "default" val a:

    String = b!! エルビス演算子 !!演算子 b != null -> b b == null -> "default"
  35. Nullableに関する演算子 val a: String = b ?: "default" val a:

    String = b!! エルビス演算子 !!演算子 禁断のNotNull強制変換 絶対に使わないこと! どうしても強制変換したい場合はrequireNotNull関数を使用する。
  36. 今後のKotlin界隈 • Kotlinに対する過度の期待からの勢い導入 • そして、失敗。挫折。 ◦ 拡張関数、演算子オーバロード、委譲プロパティの濫用とか ◦ Javaとの相互運用に関して ◦

    コーディング規約、コードレビュー、学習コスト • 銀の弾丸はない。適切な道具を適切に使うこと。 • 数年で「ブーム」から「定番」に移行
  37. まとめ • JVMは魅力的だがJava言語に課題感を持っていた→JVM言 語の台頭→Kotlin誕生 • Javaよりもコードベースをスリムに保つ ◦ 例)Extension, データクラス、プロパティ •

    NullPointerExceptionを発生させない仕組み ◦ Null安全 ◦ 扱い安さの工夫: 安全呼び出し、エルビス演算子、拡張関数let • 今はKotlinブームだがそのうち定番になる