Kotlin 1.5.0の使えそうな新機能

5月25日にKotlin 1.5.0公開記念のオンラインイベントがYouTubeで開催されていました。なんだかとてもアットホームな雰囲気で、自分が使っている言語をこの人たちが開発してくれているんだなあと思うと、Kotlinへの愛着も増すような気がしました。

今回は、1.5.0の新機能の中で、これは使えそうだなと思った機能を紹介します。

Sealed Interfaces

interfaceにsealedをつけると、そのinterfaceの実装はコンパイル時に存在するものに限られることになります。このメリットは、when式を使う場合にelseが不要になるということです。Kotlin公式サイトのソースコードを引用させてもらいながら、見ていきます。

sealed interface Polygon

fun draw(polygon: Polygon) = when (polygon) {
   is Rectangle -> // ...
   is Triangle -> // …
   // else is not needed - all possible implementations are covered
}

Polygonというinterfaceをsealedで宣言し、RectangleTriangleというクラスを実装した場合、Polygonの実装はRectangleTriangle以外には存在しないことになります。そのため、Polygonオブジェクトのクラスによって分岐するwhenの中では、RectangleTriangleについて記述すれば、elseが不要になります。コードがすっきりしてよいですね。もしもPolygonsealedではなかったとしたら、Kotlinのwhenは通常はelseが必須ですので、無駄な処理を書かなければなりません。

使いどころとしては例えば、AndroidのRecyclerViewに表示するデータをsealed interfaceで定義する、という場面がありそうです。ひとつのRecyclerViewに複数の種類のデータを表示する場合、データによってViewHolderを切り替えたりする必要がありますが、sealed interfaceを使ってスマートに記述できそうです。

あと、これまでもsealed classというのが用意されていたことを、今回初めて知りました。sealed interfaceともども、今後は活用していきたいと思いました。

Inline classes

classにvalueをつけて定義すると、ある型の別名の型を作ることができます。オーバーヘッドなしで処理できるそうです。こちらも公式サイトからの引用です。

value class Password(val s: String)

最初に見たときには、C言語のtypedefみたいなものかなあと思いましたが、うまく使うともう少しリーダブルなコードを書くことができそうです。オンラインイベントでは、「学生の時、単位をつけないと理科の先生に怒られたよね」というエピソードとともに、次のようなスニペットが紹介されていました。

value class Cents(val amount: Int)

fun payMoney(price: Cents)

payMoney(Cents(500))

確かに関数やコンストラクタの引数は、単位で混乱しやすいですので、この例のように明示的にinline classで引数を与えるようにしておくと、ミスも減るし可読性も高くなりそうです。Android StudioなどのIDEでは関数の引数の説明をポップアップで表示してくれますので、それほど苦労せずに引数の仕様を知ることができますが、それでもこの例のように型を明示的に指定することによって、コードの意図を汲み取りやすくなりますね。

まとめ

Kotlin 1.5.0で追加された新機能から、使いどころが多そうなsealed interfaceとinner classを紹介しました。

上記で紹介した以外の新機能はKotlin公式サイトに紹介されています。言語仕様の追加以外にも、パフォーマンスの改善などいろいろ進歩しているようです。概要は公式ブログの日本語ページでも読むことができます。