Java で インターフェースの定義をするコードは以下のようになります。
public interface Printable { void print(); void printDetail(); }
そしてこのインターフェースを実装した実装クラスのコードは以下のようになります
public class JavaPrinter implements Printable { @Override public void print() { System.out.println("Java summary"); } @Override public void printDetail() { System.out.println("Java detail print"); } }
実装するインターフェースを指定する部分で implements
キーワードを記述します。
以下コードで実行してみると
Printable printer = new JavaPrinter();
printer.print();
printer.printDetail();
結果は以下の通りです。当然の結果ですが。
Java summary Java detail print
ちなみに先ほどの実装クラスのJavaPrinter
は以下のように書く事もでき、@Override
アノテーションの記述なしでもコンパイルが通ります。
public class JavaPrinter implements Printable { public void print() { System.out.println("Java summary"); } public void printDetail() { System.out.println("Java detail print"); } }
Kotlinのインターフェース
KotlinとJavaは相互に呼び出し可能であることから、先ほどJavaで書いた Printable
インターフェースを Kotlinのクラスとして実装可能です。
以下のようになります
class KotlinPrinter : Printable { override fun print() { println("Kotlin summay") } override fun printDetail() { println("Kotlin detail print") } }
Kotlin ではクラス名の後ろに implements
キーワードの代わりに : (コロン)を記述して、そのあとにインターフェース名を指定します。
ちなみに、Java では継承の場合は extends
キーワードを使いますが、Kotlinの場合は継承の場合でも : (コロン)を使います。
以下は先ほどの Kotlin での実装クラスを実行するコードです
val printer : Printable = KotlinPrinter()
printer.print()
printer.printDetail()
実行結果は以下の通りです。
Kotlin summay Kotlin detail print
ちなみに実装クラスを以下のようにしようとするとコンパイルエラーとなります。
// コンパイルエラー class KotlinPrinter : Printable { fun print() { println("Kotlin summay") } fun printDetail() { println("Kotlin detail print") } }
これは、override
修飾子 がないためです。
Kotlin の override
修飾子 は、Java の@Override
アノテーションと同様に、スーパークラスやインターフェースをオーバライドするメソッドやプロパティを指定するために利用します。
しかし、Javaとは違って Kotlin の override
修飾子は省略できません。必須です。
Javaでのインターフェースしか書いていませんでしたが、Kotlinでのインターフェースの記述は以下のようになります。
interface Printable { fun print() fun printDetail() }
ちなみに、インターフェースはデフォルトの実装を持つ事ができます。
Java 8とは異なって、Kotlinではメソッドに default
というような特別なキーワードをつける必要はありません。
デフォルト実装をも持たせたインターフェースの例は以下の通りです。
デフォルト実装を持つメソッドを実装クラス側でオーバーライドしなければ、インターフェースに定義したデフォルトの処理が実行されます。
interface Printable { fun print() = println("Hello World") fun printDetail() }
さらにここに以下のようなインターフェースを登場させて
interface Display { fun print() = println("Hello Display") }
KotlinPrinterクラスに両方のインターフェースを実装させて、デフォルト実装をオーバーライドしないようにしようとするとコンパイルエラーとなります。
// コンパイルエラー class KotlinPrint : Printable, Display { override fun printDetail() { println("Detail Print") } }
複数のインターフェースから、複数の実装を継承してしまっているためです。
このようなケースでは、以下のように実装クラスで必ず対象のメソッドをオーバーライドする必要があります。
class KotlinPrint : Printable, Display { override fun print() { super<Printable>.print() super<Display>.print() } override fun printDetail() { println("Detail Print") } }
ここで super<Printable>.print()
と super<Display>.print()
の部分が継承したデフォルト実装を呼び出すコードになっています。
super.<親の型名>.{メソッド名} の記述が、継承元のメソッドを呼び出すことになります。
まとめ
Kotlin での インターフェースの定義方法と実装方法の基礎が分かりました。
まだ、この辺りだとJavaとの大きな違いは無いかなという印象です。