Java
Android
Kotlin
AtraeDay 12

JavaからKotlinに移行しはじめて思ったこと

Kotlinを書き始めた

会社で開発しているAndroidアプリをこれまでJavaで書いてきたが、10月末のAndroid Studio 3.0リリース = Kotlin正式サポートを機に、新規開発部分の実装にKotlinを使うことにした。また、既存実装部分も必要に応じて(練習も兼ねて)少しずつ書き直したりしている。

ということで、まだ1ヶ月も使ってないくらいだが、Kotlin書いてて感じたことをポツポツ書いていく。

※ちなみに、既存の部分の書き換えに関しては、Android Studio(≒ IntelliJ)の自動コンバート機能が非常に優秀。ファイルごと変換するのも楽だし、Javaのコードを部分的にコピーして.ktのファイルにペーストすると変換してくれるのも嬉しい。

オプショナルの存在がありがたい

もう改めて書く必要も無いことだけど、やはり挙がるのがこれ。

同じくネイティブアプリを書くときに利用するSwiftと比較して、ぬるぽの発生を気にしながら書かなければいけないのが不安要因だったが、これで解消された。もちろんJavaでもNullチェックをしたりOptional.ofNullableを使ったりして回避そのものはできるものの、NullableやNotNullがはっきりと分かれている世界になって良かった。

エルビス演算子使って、Swiftのguardぽく書けたりするの好きです。

sample.kt
val str: String = optionalStr ?: return

オプショナルの良さを消さないためには、Java側でもケアが必要

JavaとKotlinが入り混じったプロジェクトを扱う場合、当然ながらKotlinからJavaのコードを呼び出すケースが出てくる。そういうときには、Java側でアノテーションを付けてあげると、Kotlinでのオプショナル関連の制約が効くようになる。

例えば、Java側で以下のようなコードがあったとする。

AppUtil.java
public class AppUtil {
    public static String getVersion() {
        return "1.0";
    }
}

Kotlin側から呼び出すとAppUtil.getVersion()の返り値はString!となり、StringでもString?でも許容しているような状態になってしまう。うっかりnullでも入ってしまうとぬるぽ時代に逆戻り。これでは持ち味が消えてしまうので、Java側のメソッドに@NonNull@Nullableアノテーションを付けてあげる。これで、IDEが返り値の型をStringもしくはString?だと推論してくれるようになる。

extensionが便利

既存のクラスにメソッドやプロパティを新しく生やせる。Javaで書いていた頃は、Swiftと比較してこれが無いのが不便な感じだった。(実現するために、HogeUtilみたいなクラスのstaticメソッドが結構な数生まれていた)

Extension.kt
fun Button.disableTouch() {
    alpha = 0.5f
    isEnabled = false
}

上記はandroid.widget.Buttonにメソッドを追加した例。

Javaにおけるstaticメソッド・static変数 etc.

よく使っていたstaticメソッドやstaticプロパティがKotlinには存在しない。例えば、フラグメントのファイルにだいたい書いていたpublic static HogeFragment newInstance(...) { ... }みたいなファクトリメソッドはどう表現すれば良いのかというと、解決法の1つとしてCompanion Objectを使うという手がある。

HogeFragment.kt
class HogeFragment : Fragment() {
    companion object {
        fun newInstance(...): HogeFragment {
            ...
        }
    }
}

※ただしこのままだと、Javaから呼び出す際にHogeFragment.Companion.newInstance(...)という呼び方をしなければならず、ちょっと不格好。Javaで書いたときのようにHogeFragment.newInstance(...)と呼び出したい場合は、メソッドにアノテーション@JvmStaticを付ける。

HogeFragment.kt
companion object {
    @JvmStatic
    fun newInstance(...): HogeFragment {
        ...
    }
}

一方で、staticメソッド(ぽいもの)を表現する方法としては、ファイルのトップレベル関数を使う手もある。

HogeFragment.kt
fun topLevelFun(...) {
    ...
}

class HogeFragment : Fragment() {
    ...
}

Javaのときと同じように呼べること・名前の衝突を気にしなくてよいことなどから、基本的に前者の方法(Companion Object使う方)で良いかと思っていた。が、以下のブログなどを最近読んで、使い分けのなんとなくのイメージがついて勉強になりました。
companion object vs. top-level - hydrakecat’s blog

static変数に関しても同様で、Companion Objectの中でプロパティを宣言する方法とトップレベルで宣言する方法がある。(前者に関しては、@JvmFieldを付けるとJavaのときと同様の呼び出し方ができる)

おわり

ということで、まだまだ使い始めて日が浅いけど、Kotlin書いてて感じたことを少しだけ書いた。

上で書いてきたことに加え、Swiftと書き味が似ていることやコード量がJavaと比較して減ることも嬉しい。サーバサイドで利用するのもありなんじゃないかと思っている。

[PR] 仲間探してます

アトラエで一緒にKotlinやSwift, RailsやPythonを書いてくれる仲間を募集中です!
https://www.green-japan.com/company/172