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
で宣言し、Rectangle
とTriangle
というクラスを実装した場合、Polygon
の実装はRectangle
とTriangle
以外には存在しないことになります。そのため、Polygon
オブジェクトのクラスによって分岐するwhen
の中では、Rectangle
とTriangle
について記述すれば、else
が不要になります。コードがすっきりしてよいですね。もしもPolygon
がsealed
ではなかったとしたら、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公式サイトに紹介されています。言語仕様の追加以外にも、パフォーマンスの改善などいろいろ進歩しているようです。概要は公式ブログの日本語ページでも読むことができます。