Help us understand the problem. What is going on with this article?

業務でKotlinを書いている僕がKotlinを書く際に個人的に注意していること

More than 3 years have passed since last update.

Kotlinアドベントカレンダー201518日目の記事です。

はじめに

どうも、CyberAgentでAndroidエンジニアをしている@magiepoohです。
現在、AmebaFRESH!という動画サービスをKotlinを使って開発中です。というわけで、業務でKotlinを書いている僕がKotlinを書く時に注意していることを幾つか書き留めればと思います。
※ かなり 個人的に 注意していることなので「ふ~ん」程度に読んでいただけると有り難いです。

早期リターン

早期リターンはKotlinに限った話ではありませんが、JavaではよくNullチェックしてNullだったらreturnみたいなことをすると思います。
Kotlinでは?:(エルビス演算子)を使って、書くことができます。

fun hoge(name: String?) {
    name ?: return
    // something
}
void hoge(String name) {
    if (name == null) {
        return;
    }
    // something
}

Javaに比べてかなり簡潔です

Nullableな変数をNonNullなものに

Nullableな変数を仕様していると?だらけになってしまいます。先ほどの早期リターンと組み合わせてNullableな変数をNonNullなものに変えていくのもいいかもしれません。

fun hoge(name: String?) {
    name ?: return
    name.toUpperCase() // NonNullなので?が不必要
}

Smartcastは地味に便利

Javaではよくcastを行ったものを変数に入れたりしていました。わざわざ変数に入れなくても解決する場面もあるかもしれません。

override fun onBindViewHolder(holder: RecyclerView.ViewHolder?, position: Int) {
    holder as ViewHolder
    holder.hoge // ViewHolderクラスへSmartcastされている 
}

もちろん以下の様に、Stringじゃなかったらreturnなども可能です。ただ、必ずキャストしなければならない場合(あまりないですが)には、上記の方法もありかなと思います。

if (x !is String) return
print(x.length) // x is automatically cast to String

スコープ関数を適切に使う

スコープ関数はご存知でしょうか?
知らない方はKotlinエバンジェリストたろうさんが良記事を書いてくださっているのでそちらを御覧ください。

例としてAndroidのソースコードからViewの高さを変更する場合を考えてみます。方法としてはLayoutParamsをgetしてheightフィールドに値を入れて、再びsetしてあげることになると思います。

LayoutParams layoutParams = targetView.getLayoutParams();
layoutParams.height = 100;
targetView.setLayoutParams(layoutParams);

Kotlinの場合はapplyを使うと以下の様に書くことができます。

targetView.layoutParams = targetView.layoutParams.apply { height = 100 }

わかりやすい。
わかりやすすぎる。。
美しく書けます。特にAndroidでいうとIntentの生成を始め、何かを自身に設定するような場面でガンガン使えて、完結になっていくと思います。

また、runを使う例も考えてみましょう。今回は例として正規表現のテストを書くとします。

findChannel("$BASE_URL/hoge").run {
    assertTrue(find())
    assertThat(group(1), _is("hoge"))
}

このように簡潔に書くことができます。

itに適切に名前を付ける

Kotlinを書いている時に以下のような時がよくあります。

hoge?.let {
    it.do()
    // ...
    // ...
    // ...
    it.complete()
}

このように処理が長くなる(もしくはネストが多い)場合に、itが何を指しているのかが分からなくなるかもしれません。そういう場合に関しては適切な名前を付けて読みやすくしてあげるといいでしょう。

hoge?.let { hoge ->
    hoge.do()
    // ...
    // ...
    // ...
    hoge.complete()
}

({ }) -> { }

Rxを使用している時によくあるのですが、ちゃんと省略できるところは意識しましょう。

.subscribe { // bad: subscribe({ ... })
    // ...
}

setHoge -> Hoge property property access

Kotlinではプロパティをよく使います。getter,setterではなくできるだけプロパティを使ってあげる方がKotlinっぽくなると思います。

// bad
something.setListener(listener)
// good
something.listener = listener

おわりに

KotlinをよりKotlinらしく書けるように意識している小さなTipsを紹介しました。個人的な意見なので間違ってるかもしれませんし、また、こうしてるよーという意見もあればどんどん勉強したいのでコメントいただけたら嬉しいです!

明日は @droibit さんです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした