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

はじめてのKotlinハンズオン #DroidKaigi

Taro Nagasawa
February 09, 2018

はじめてのKotlinハンズオン #DroidKaigi

Taro Nagasawa

February 09, 2018
Tweet

More Decks by Taro Nagasawa

Other Decks in Programming

Transcript

  1. 簡単!Better Java public final class User { private final Long

    id; private final String name; public User(final Long id, final String name) { this.id = id; this.name = name; } public Long getId() { return id; } public String getName() { return name; } @Override public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final User user = (User) o; if (!id.equals(user.id)) return false; return name.equals(user.name); } @Override public int hashCode() { int result = id.hashCode(); result = 31 * result + name.hashCode(); return result; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + '}'; } } 筋力と視力が 重要だ... Javaで書くと...
  2. 簡単!Better Java data class User(val name: String, val id: Long?)

    サイコー以外の 言葉が見つから ない Kotlinで書くと...
  3. 基本的にはJavaにそっくり fun main(args: Array<String>) { println(123) // 123 println(10 +

    2 * 3) // 16 println(5 / 2.0) // 2.5 println(true && true) // true println('A') // A println("Hello".toUpperCase()) // HELLO }
  4. 推論できるところは大抵 型を省略できる • 関数の戻り値の型 • ラムダ式の引数の型 • 型引数 val hoge

    = "I love Kotlin" val fuga = hoge.reversed() val piyo = fuga.length この他に などが省略可能な場合がある
  5. 文字列リテラルが便利だよ! val name = "おにぎり" val price = 120 println("${name}が3個で${price

    * 3}円です") val html = """<div> <p>Hello, world!</p> </div>""" println(html) 文字列テンプレート raw-string
  6. if-else: Javaとほぼ同じ fun main(args: Array<String>) { if (args.size > 0)

    { println("こんにちは、${args[0]}さん") } else { println("こんにちは、名無しさん") } }
  7. if-else: Kotlinでは式である fun main(args: Array<String>) { val name = if

    (args.size > 0) args[0] else "名無し" println("こんにちは、${name}さん") }
  8. forループ fun main(args: Array<String>) { val names = listOf("foo", "bar",

    "baz") for (name in names) { println(name) } } リストを生成する関数
  9. forループ fun main(args: Array<String>) { val names = listOf("foo", "bar",

    "baz") for (name in names) { println(name) } } 繰り返し可能なオブジェクトに対して 要素を順に取り出す
  10. レンジ fun main(args: Array<String>) { var sum = 0 for

    (i in 1..10) { sum += i } println(sum) // 55 }
  11. レンジ fun main(args: Array<String>) { var sum = 0 for

    (i in 1..10) { sum += i } println(sum) // 55 } 「1から10まで」のレンジ(範囲) オブジェクトを生成する
  12. まとめ • リテラルや演算子などはJavaにそっくり • 再代入OKな変数宣言 var、再代入NGな変数宣言 val • 型推論により型の記述を省略可能 •

    文字列リテラルが便利: 文字列テンプレート、raw-string • if-elseは式である • forループは、Javaの拡張for文に似ている • listOf関数により、リストをつくることができる • 範囲を表すレンジオブジェクト (e.g.) 1..5 • whileループは、Javaとほぼ同じ
  13. 関数入門 fun add(a: Int, b: Int): Int { return a

    + b } fun main(args: Array<String>) { val sum = add(3, 7) println(sum) // 10 }
  14. 関数入門 fun add(a: Int, b: Int): Int { return a

    + b } fun main(args: Array<String>) { val sum = add(3, 7) println(sum) // 10 } これが関数
  15. 関数入門 fun add(a: Int, b: Int): Int { return a

    + b } fun main(args: Array<String>) { val sum = add(3, 7) println(sum) // 10 } 関数を定義するためのキーワード
  16. 関数入門 fun add(a: Int, b: Int): Int { return a

    + b } fun main(args: Array<String>) { val sum = add(3, 7) println(sum) // 10 } 関数の名前
  17. 関数入門 fun add(a: Int, b: Int): Int { return a

    + b } fun main(args: Array<String>) { val sum = add(3, 7) println(sum) // 10 } 引数リスト
  18. 関数入門 fun add(a: Int, b: Int): Int { return a

    + b } fun main(args: Array<String>) { val sum = add(3, 7) println(sum) // 10 } 戻り値の型
  19. 関数入門 fun add(a: Int, b: Int): Int { return a

    + b } fun main(args: Array<String>) { val sum = add(3, 7) println(sum) // 10 }
  20. 関数入門 fun add(a: Int, b: Int): Int { return a

    + b } fun main(args: Array<String>) { val sum = add(3, 7) println(sum) // 10 }
  21. 関数入門 fun add(a: Int, b: Int): Int { return a

    + b } fun main(args: Array<String>) { val sum = add(3, 7) println(sum) // 10 }
  22. 関数入門 fun add(a: Int, b: Int): Int { return a

    + b } fun main(args: Array<String>) { val sum = add(3, 7) println(sum) // 10 }
  23. 関数入門 fun add(a: Int, b: Int): Int { return a

    + b } fun main(args: Array<String>) { val sum = add(3, 7) println(sum) // 10 }
  24. 単一式関数 fun add(a: Int, b: Int): Int { return a

    + b } fun add(a: Int, b: Int): Int = a + b fun add(a: Int, b: Int) = a + b 型を省略するのは楽だけど 明示した方が読み返したときに わかりやすい!
  25. [課題] いろんな関数をつくって遊ぼう 下記の様な関数を作る。 • 引数として与えられた整数を2乗した数を返す関数square • 引数として与えられた2つの整数のうち、大きい方を返す 関数max • 引数として与えられた整数が偶数の場合にtrueを、それ

    以外の場合にfalseを返す関数isEven • 引数として与えられた整数の階乗を返す関数factorial ◦ 例)4の階乗 = 4 * 3 * 2 * 1 • 引数として与えられた整数に、3が含まれるかどうかを返 す関数containsThree
  26. クラスの定義 class Person(val name: String) val taro: Person = Person("Taro")

    println(taro.name) // Taro クラスの定義 インスタンス生成=コンストラクタ呼び出し
  27. クラスの定義 class Person(val name: String) val taro: Person = Person("Taro")

    println(taro.name) // Taro プライマリコンストラクタとその引数リスト
  28. メソッドの定義 class Person(val name: String) { fun introduceMyself() { println("I

    am ${name}") } } val taro: Person = Person("Taro") taro.introduceMyself() // I am Taro
  29. [課題] クラスの定義 • クラス名 IntPair • 2つのプロパティを持つ ◦ first: Int

    ◦ second: Int • 3つのメソッドを持つ ◦ sum: firstとsecondの和を返す ◦ max: firstとsecondのうち大きい方を返す ◦ swap: firstとsecondが逆になったIntPairオブジェクトを返す
  30. クラスが実装すべき便利メソッド class IntPiar(val first: Int, val second: Int) { //

    省略 override fun toString(): String = "IntPair(first=$first, second=$second)" } • toStringメソッド • equals/hashCode   → 機械的に導き出すことができる
  31. データクラス data class IntPiar(val first: Int, val second: Int) {

    // 省略 } fun main(args: Array<String>) { val oneAndTwo = IntPair(1, 2) println(oneAndTwo) // IntPair(first=1, second=2) println(oneAndTwo == IntPair(1, 2)) // true println(oneAndTwo === IntPair(1, 2)) // false }
  32. 拡張関数 fun String.hello() { println("Hello, ${this}!") } val name =

    "world" name.hello() // Hello, world! 「クラス名.」がミソ
  33. 拡張関数 fun String.hello() { println("Hello, ${this}!") } val name =

    "world" name.hello() // Hello, world! メソッドのようにthisが使える this: 自分自身への参照
  34. 拡張関数 fun String.hello() { println("Hello, ${this}!") } val name =

    "world" name.hello() // Hello, world! メソッドのように呼び出せる
  35. まとめ • クラスやオブジェクト、インスタンスの考え方はJavaとほぼ同じ • クラスはプライマリコンストラクタを持つ • クラスはメソッドを持つことができる • クラスはプロパティを持つことができる •

    プライマリコンストラクタの引数を、そのままプロパティとして宣 言することができる • インスタンス生成の際にnewのようなキーワードは不要 • 既存のクラスにメソッドを追加するような「拡張関数」というもの を定義できる
  36. 安全呼び出し s?.length if (s != null) s.length else null 同じ

    if-elseは式 (評価されて値になる) foo?.bar()?.baz()?.qux() メソッドチェーンで役立つ
  37. 今日登場しなかったキーワード • インタフェース • 抽象クラス • ラムダ式 • 委譲プロパティ •

    シールドクラス • 列挙型 • ジェネリクス • コルーチン • クラス委譲 • 演算子オーバロード など...
  38. 本日のまとめ • KotlinはBetter Java(とはいえJSやNativeも対象) • Kotlinの特徴は、簡単・安全・Android対応・Javaとの親和性 • Javaと似ている文法も多くある • 強力な型推論、文字列テンプレート、if-else式などが簡潔な

    コードの実現に寄与 • クラスはメソッドとプロパティ、プライマリコンストラクタを持つこ とができる • 既存の型に対してメソッドを追加するような拡張関数 • NotNullとNullableを厳格に区別してNull安全に • データを表現するクラスはデータクラスにすると便利