LoginSignup
2
2

More than 5 years have passed since last update.

Kotlinのチュートリアルをやってみた④

Posted at

前回に引き続きSwiftエンジニアがKotlinのチュートリアルを進めます。今回はDestructuring declarations and Data classesの章です。
http://try.kotlinlang.org/#/Examples/Destructuring%20declarations%20and%20Data%20classes/Destructuring%20declarations/Destructuring%20declarations.kt

自分が実装した分のリポジトリ

https://github.com/akatsuki174/KotlinTutorial
上記のDestructuringDeclarationsAndDataClasses.ktファイル

Destructuring declarations and Data classes

Destructuring declarations

fun main(args: Array<String>) {
    val pair = Pair(1, "one")
    val (num, name) = pair

    println("num = $num, name = $name")
}

class Pair<K, V>(val first: K, val second: V) {
    operator fun component1(): K {
        return first
    }

    operator fun component2(): V {
        return second
    }
}

ここでは分解宣言というものを学びます。分解宣言をすると一度に複数の変数を作成できます。つまりこんなことができるということです。

val (num, name) = pair

複数の値を返すようにするために、componentN関数を用意しています(Nの部分は任意の整数です)。そのため、このように値を取得することもできます。

val pair = Pair(1, "one")
val num = pair.component1()
val name = pair.component2()

Data classes

data class User(val name: String, val id: Int)

fun getUser(): User {
    return User("Alex", 1)
}

fun main(args: Array<String>) {
    val user = getUser()
    println("name = ${user.name}, id = ${user.id}")

    // or

    val (name, id) = getUser() // 分解宣言
    println("name = $name, id = $id")

    // or

    println("name = ${getUser().component1()}, id = ${getUser().component2()}")
}

Kotlinにはデータを保持するだけのためのクラス、データクラスがありdataを宣言時に付与します。データクラスを作ると、プライマリコンストラクタから推測してtoString(), equals(), hashCode(), copy()が使用できるようにしてくれます。これら関数の用例についてはAutogenerated functionsの章で扱います。

データクラスは以下の要件を満たす必要があります。

  • プライマリコンストラクタは少なくとも1つのパラメータを有すること
  • プライマリコンストラクタのパラメータはvalまたはvarを付けること
  • abstract, open, sealed, innerにしない

※Kotlin1.1からデータクラスは他のクラスを拡張することができるようになりました。

最後にcomponentN関数についてです。プライマリコンストラクタで宣言した数、順番に応じて作成されます。そのためgetUser().component1()と書くとコンストラクタの1つめに書いたnameが返却されます。

Traversing a map

fun main(args: Array<String>) {
    val map = hashMapOf<String, Int>()
    map.put("one", 1)
    map.put("two", 2)

    for ((key, value) in map) {
        println("key = $key, value = $value")
    }
}

kotlinにもmapが存在し、上記のように使うことができます。以下のように要素を取得することもできます。

println("value = ${map.get("one")}")
println("value = ${map["two"]}")

初期化時に値を入れたい場合はこのように書くことができます。

val map2 = hashMapOf("一" to 1, "二" to 2)
println("value = ${map2.get("")}")

また、JavaのようにLinkedHashMap, SortedMapも使えます。

val linkedMap = linkedMapOf("mikan" to "🍊", "apple" to "🍎")
val sortedMapOf = sortedMapOf("mikan" to "🍊", "apple" to "🍎")

HashMapに関する詳しい情報は公式のHashMapのページを御覧ください。

Autogenerated functions

data class User(val name: String, val id: Int)

fun main(args: Array<String>) {
    val user = User("Alex", 1)
    println(user) // toString()

    val secondUser = User("Alex", 1)
    val thirdUser = User("Max", 2)

    println("user == secondUser: ${user == secondUser}")
    println("user == thirdUser: ${user == thirdUser}")

    // copy() function
    println(user.copy())
    println(user.copy("Max"))
    println(user.copy(id = 2))
    println(user.copy("Max", 2))
}

Data classesの章でデータクラスについて軽く学びましたがここではもう少し深く学びます。データクラスはtoString(), equals(), hashCode(), copy()が自動で作られます。

toString():上記の例にあるようにprintln([オブジェクト])で使うこともできますし、user.toString()という形で呼び出すこともできます。出力結果はUser(name=Alex, id=1)となります。

equals():中身が同じオブジェクトかどうかの判定は上記の例にあるようにuser == secondUserで表すこともできますが、user.equals(secondUser)という書き方をすることもできます。

hashCode():ハッシュコードを出力してくれます。63347075のような形で出力されます。

copy():上記の例で出ているようにオブジェクトをコピーできます。上記の例の実行結果は以下の通りです。

println(user.copy())            // User(name=Alex, id=1)
println(user.copy("Max"))       // User(name=Max, id=1)  user.copy(name = "Max")と同義
println(user.copy(id = 2))      // User(name=Alex, id=2)
println(user.copy("Max", 2))    // User(name=Max, id=2)

感想

ファイル名の色の意味がわかりづらい

KotlinそのものではなくIDEAの話になります。

ある時、ファイル名が赤くなっているものがあることに気づきました。というか白と青まである。
スクリーンショット 2017-04-23 1.42.29.png

赤ってことはエラーがあるのか??と思ったものの、正常に実行できます。調べてみたこと、試してみたことを考え合わせると、Gitへのコミット状態によって色が変化しているようでした。

ファイルの色 意味
全てコミット済み
コミットされていない部分がある
新しく追加したファイルでまだコミットしていない

Xcodeで言うと以下の状態と同じです。

スクリーンショット 2017-04-23 9.30.14.png

マークの種類 意味
なし 全てコミット済み
M コミットされていない部分がある
A 新しく追加したファイルでまだコミットしていない

個人的には色よりマークで示してくれた方が「え?エラー??」とか焦らずにいられて良いなと思いました。

分解宣言が便利そう

Swiftでも次のようにdictionaryを分解宣言することはできます。

let dictionary = ["one":1, "two":2, "three":3]        
for (key, value) in dictionary {
    print("key is \(key), value is \(value)")
}

しかしクラスに対して行うことはできないのでKotlinの方がより柔軟性が高く、使いどころの幅も広がるかなと思いました(ただ、プロパティが多くて分解時に変数が多く生成されてしまって逆に使い勝手(見栄え?)が悪くならないのだろうかと思ったりもしています)。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2