Kotlinでこんなところがいいなーってところ

Kotlinはいいぞ

きっかけはこのツイート、これでKotlinに興味を持ちました。

Android StudioやIntelli Jでの導入はプラグイン入れて、KotlinのビルドをされるようにしてJavaのコードをKotlinに変換するだけ。
全部ボタンポチポチするだけです。導入は他の記事に任せます。

Javaが動けばKotlinも動く。
KotlinからJavaJavaからKotlinを呼ぶことができる。

かなり快適で、今後もKotlinでAndroidアプリを開発していきます。

Kotlinいいところ

null安全,型推論,new要らない,セミコロン要らない

val builder = StringBuilder("")

new

書かなくていいんです。
書く必要無いよね。

val

valは型推論とfinalの両方の意味を持つ。
型推論だけならばvar
finalって書く必要がない場所はいつもfinalって書いてなかったけどvalで済むならval使うよね。
変な所で代入されてたとかを防げる

セミコロン要らない

セミコロン要らない言語初めてだったので改行できないの?って思って居ましたがそんなことはなかった。以下のように書ける。

val builder = StringBuilder("お")
builder
        .append("っ")
        .append("ぱ")

null安全

明示しない限り絶対にnullではない。
なのでnullチェックが要らない。
null許容したい場合はこう。

val builder : StringBuilder? = StringBuilder("")

そしてnullである可能性があるならば必ずnullチェックをする必要がある。

val builder : StringBuilder? = StringBuilder("お")
if (builder != null) {
    // この中ではbuilderは「StringBuilder?」ではなく「StringBuilder」として扱われる。
    // これをスマートキャストと言う
    builder.append("っ")
}

// こういう書き方でも良い。?はnullなら以降は実行しない。
builder?.append("ぱ")

最近はこんな書き方をしている。良いのかは分からない。
値を渡していってnullになった時点でreturn

// ?: は左がnullなら右を代入する

// このコードはIDEがAllways nullって警告するけど
// builderがnullなら StringBuilder("") を代入
// これが一般的な使い方?だと思う
var builder: StringBuilder? = StringBuilder("")
builder = null
builder = builder ?: StringBuilder("")

// HogeとFugaはnullを返すかもしれない
// どんどん値を加工していって、null(エラー)になった時点でreturnしてくれる
val hoge = Hoge("") ?: return
val fuga = Fuga(hoge) ?: return

入力補完

こう書きたい

@Override
protected void onDestroy() {
    super.onDestroy();
}

Kotlinだとこう
onの時点で入力補完が効きます。 super.onDestroy()まで補完してくれます。
ありがたい。

// アノテーションはこうなる
override fun onDestroy() {
    super.onDestroy()
}

条件式

Kotlinにはswitchの代わりにwhenがあります。

Kotlinではwhenもifも式です。
値を返してくれます。

val isBlue = true
val hoge = if(isBlue){
    "青です" // 最後に来たものを hoge へ代入
}else{
    "青ではありません" // 最後に来たものを hoge へ代入
}

// 因みに三項演算子は無いのでワンライナー(一行)で書きたい場合はこれを利用します。
val fuga = if(isBlue) "青" else "not青"

// whenで書くと
val color: String = "青"
val piyo = when (color) {
    "青" -> "blue"
    "赤" -> "red"
    else -> "other"
}

Javaで夢見るswitchでinstanceof

型によって条件分岐できます。instanceofしなくていいよ!
というか定数以外も全然行けます。かなり柔軟

// anysの型は Array<Any> になる
val anys = arrayOf("おえういあ", 0, 9L)

anys.forEach {
    val result = when (it) {
        is String -> {
            // is String って言ってるんだから String なのは明白
            // ここでもスマートキャストされ、it は String として扱われる
            val result = it
                    .replace("う", "ぱ")
                    .replace("あ", "")
                    .replace("え", "っ")

            "String : $result" // 値を返す
        }
        is Int -> {
            // ダブルクォーテーションの中で $変数名 ${式} とかできるのも強い
            "Int : ${it + 1}" // 値を返す
        }
        is Long -> {
            "Long : ${it + 0.1}" // 値を返す
        }

        // 値を返す場合は必ず else が必要。値を返さない場合は要らない。
        else -> throw IllegalStateException()
    }

    println(result)
    // String : おっぱい
    // Int : 1
    // Long : 9.1
}

キャスト

キャストは asでできるよ () 書かなくて済むよ、やったね asもnull安全関連で色々あるけど省略

val hoge = 変換したいの as 変換先

lateinit

bundleで受け取ったnullではない構造体とかをフィールドに含めたい。
null安全なので何か入れないといけないけどインスタンス生成するのは嫌だ。 そこで lateinit

class MainActivity : AppCompatActivity() {

    // 初期化しないといけないので lateinitがないとこうなる
    var data : HogeData = HogeData()

    // もしくはこう
    var data : HogeData? = null

    // こうすれば解決
    // 意味はそのままで初期化を待ってくれる。
    lateinit var data : HogeData

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Kotlinで getIntent() は intent と書ける
        data = intent.extras.getSerializable("data") as HogeData
    }
}

おわり

こういうブログ書くの初めてでなんかごちゃごちゃしてしまった。
説明するってのは大変だなぁ…

言葉の意味とかコードの内容とか自信がないのでご指摘あればコメント欄に。

Kotlinでガッツリ書いたアプリ第一弾です。
matsudamper.hatenablog.jp