Kotlinのきほん インターフェイス編
はじめに
SpringFesta2018に参加してKotlinの話をいたるところで聞き、Kotlinを今日から勉強していこうと思います。参考にする本はこれ。

- 作者: Dmitry Jemerov,Svetlana Isakova,長澤太郎,藤原聖,山本純平,yy_yank
- 出版社/メーカー: マイナビ出版
- 発売日: 2017/10/31
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
Kotlinを開発した人が書いているので言語の目指すところや、奥深い内容を理解できるんじゃないかなと思います。時間があったらKotlinの書き方だけではなくて思想や今後の動きについてもまとめていきたいと考えています。
私は物忘れが激しいのでチートシートも見ながら進めます。
Kotlinチートシート発見
— bookstore (@bookstoreTech) 2018年11月4日
Kotlin Cheat Sheet by @marcinmoskala https://t.co/VMRTuvIIeP
セットアップ
開発環境は以下の通り。
※ IntelliJはCommunity EditionでもKotlinの開発を行うことができます。
Kotlinのクラスと愉快な仲間たち
こんな種類があります。
- クラス
- 抽象クラス
- インターフェイス
- データクラス
- 内部クラス
- ネストクラス
- シールドクラス
- クラス委譲
- コンパニオンオブジェクト
なかなか多いです。ので、今回はインターフェイスを中心に取り上げます。
インターフェイス
Kotlin公式サイトのインターフェイスに関するドキュメントはこれ
interface User { fun activate(): Boolean }
基本的にはJavaと同じです。これを実装するクラスには、宣言されているメソッドを実装する義務が発生します。でなければコンパイルエラーになります。
インターフェイスのメソッド宣言を実装する場合、overrideキーワードを付けることは必須です。Javaのようにアノテーションでつけなくても怒られないなんてことはありません。
class Employee( val name: String, val postalCode: String ) : User { // 必ずoverrideはつけないといけない override fun activate(): Boolean { return true } }
インターフェイスにプロパティを宣言
Javaと違うところは、インターフェイスにプロパティを宣言できることです。
interface User { fun activate(): Boolean val name: String }
実際にはインターフェイスが値を持つのではなくて、これを実装するクラスが値をもつことになります。なので、ここで宣言しているのは実装クラスはnameの値を取得する手段を持たなくてはならないと言うことになります。実際に、このインターフェイスを実装するクラスは以下のようになります。
class Employee( override val name: String, // nameの値をセット private val postalCode: String ) : User { override fun activate(): Boolean { println("activate $name") return true } }
Employeeのプライマリコンストラクタに対してoverrideキーワードを使用し、nameを持たせました。こうすることでEmployeeはUserの宣言内容を満たすことが出来ます。
fun main(args: Array<String>) { val user : User = Employee(name = "BookStore", postalCode = "12345") println(user.name) println(user.activate()) }
// 出力 BookStore activate BookStore true
インターフェイスのデフォルト実装と衝突
Javaは8からインターフェイスに対してデフォルト実装をすることができるようになりました。Kotlinも出来ます。
interface User { fun activate(): Boolean { println("Activate By User") return true } }
ですが、同時に以下のような同じデフォルトメソッドを持つインターフェイスがあり、同時に実装するとどうなるかと言うと、オーバーライドが強制されます。
interface Actionable { fun activate(): Boolean { println("Activate By Actionable") return true } } class Employee( val name: String, val postalCode: String ) : User , Actionable { // 必ずオーバーライドしなくてはいけない override fun activate(): Boolean { return true } }
理由は当然で、このままだとどちらのメソッドを呼び出せばいいかわからないからですね。ただ、このようにインターフェイスのデフォルト実装が衝突するというのはアーキテクチャ的にいけてない場合なんじゃないかと思います。
ちなみに、デフォルト実装を呼び出すことは出来ます。
class Employee( val name: String, val postalCode: String ) : User , Actionable { override fun activate(): Boolean { super<User>.activate() super<Actionable>.activate() return true } }
おわりに
Kotlinを知るたびに「KotlinってJavaが少し便利になったやつでしょ?」と思っていた頃の自分を殴りたいです。次は多分抽象クラスとクラスのことについて書きます。