Kotlinにおける継承、オーバーライド、抽象クラス、インタフェースとスマートキャスト:Android Studioで始めるKotlin入門(5)(2/3 ページ)
Android Studio 3.0を使い、最近話題のプログラミング言語「Kotlin」の特徴を解説する連載。今回は、「継承」など、「クラス」周りの機能を扱っていきます。また、継承に関連して「スマートキャスト」機能についても解説します。
インタフェース
Kotlinのインタフェースの使い方はリスト6のようになります。
//インタフェースの定義例
interface Flyable{
fun fly()
}
//インタフェースの実装例
class Airplane: Vehicle(), Flyable{
override fun run(){
println("Running on runway!")
}
//インタフェースのメソッドを実装(実装しないとコンパイルエラー)
override fun fly(){
println("Flying!")
}
}
……
//インタフェースを実装したクラスの使用
val airplane = Airplane()
airplane.run() //「Running on runway!」
airplane.fly() //「Flying!」
インタフェースを実装する際に、Javaの「implements」キーワードではなく、クラス継承と同様に「:」の後に記述する点に注意してください。また、インタフェースのメソッドを実装する際もoverrideキーワードを付けてオーバーライドを明示的に宣言する必要があります。
また、Java 8でインタフェースのデフォルト実装がサポートされましたが、Kotlinでもリスト7のように実装を持つインタフェースを使用できます。
//実装を持つインタフェースの定義例
interface Stoppable{
fun stop(){ print("Stopped slowly...") }
}
//実装を持つインタフェースの実装例
class StoppableVehicle: Vehicle(), Stoppable{
override fun run(){
println("Running!")
}
}
さて、Javaのインタフェースは基本的にメソッドを記述するのが中心で、フィールドについては全て定数で、自動的に「final public static」が指定されることになっています。つまり、インスタンスごとのフィールドを宣言することはできません。
一方Kotlinでは、リスト8のようにインタフェースにもプロパティを持つことができます。
//プロパティを持つ(!)インタフェース
interface Limiter{
//プロパティを定義できるが、実際には「abstract」として扱われる
val maxSpeed: Int
//デフォルト実装からプロパティを参照できる
fun boost(speed : Int){
if(speed > maxSpeed){
println("Overspeed!")
}else{
println("Boosted to $speed")
}
}
}
//プロパティを持つインタフェースの実装例
class CarWithLimiter: Vehicle(), Limiter{
//インタフェースのプロパティを明示的に実装する必要あり
override var maxSpeed : Int = 100
override fun run(){
println("Running!")
}
}
……
//プロパティを持つインタフェースを実装したクラスの使用
val carWithLimiter = CarWithLimiter()
carWithLimiter.run() //「Running!」
carWithLimiter.boost(120) //「Overspeed!」
//プロパティの内容がインスタンスごとであることを確認するため、もう1つインスタンスを作成
val carWithLimiter2 = CarWithLimiter()
//1つ目のインスタンスのmaxSpeedプロパティを書き換える
carWithLimiter.maxSpeed = 200
carWithLimiter.boost(120) //「Boosted to 120」maxSpeedが書き換わっているので問題なくブースト可能
carWithLimiter2.boost(120) //「Overspeed!」2つ目のインスタンスのmaxSpeedは書き換わっていない
ここでは、乗り物の制限速度機能を表す「Limiter」インタフェースに最高速度の「maxSpeed」プロパティを宣言しています。加速するための「boost」メソッドではmaxSpeedプロパティを参照して、指定速度まで加速可能かどうかを判定しています。
もちろん、Kotlinのインタフェースの仕組みもJavaと同様、実際には状態を持つことはできませんので、インタフェースに宣言するプロパティはアクセサ(getter、setter)を持つか、あるいは「abstract」でなければなりません。
LimiterインタフェースのmaxSpeedプロパティにはアクセサを指定していないため、abstractとして扱われます。そのため、Limiterインタフェースを実装する「CarWithLimiter」クラスで、maxSpeedプロパティをoverrideキーワード付きで継承することで、実際に値を保存する場所を確保しています。
このサンプルでは、maxSpeedプロパティがインスタンスごとに値を持っていることを確認するため、2つのCarWithLimiterインスタンスを使っています。
デフォルト実装の解決
さて、インタフェースのデフォルト実装はとても便利な機能ですが、複数のインタフェースを実装する際、リスト9のようにデフォルト実装したメソッド名がぶつかることがあります。
interface Stoppable{
fun stop(){ print("Stopped slowly...") }
}
//同名の「stop」メソッドを持つインタフェース
interface Stoppable2{
//名前のぶつかるメソッド
fun stop(){ print("Stopped suddenly!!!") }
//名前のぶつからないメソッド
fun crash(){ print("Crash!!!") }
}
……
//同じ名前のメソッドを持つインタフェースを複数実装した例
class StoppableVehicle2: Vehicle(), Stoppable, Stoppable2{
override fun run(){
println("Running!")
}
//stopメソッドを定義しないとコンパイルエラーになる
override fun stop(){
print("Original stop implementation!")
super<Stoppable>.stop() //Stoppableのデフォルト実装を呼び出す
super<Stoppable2>.stop() //Stoppable2のデフォルト実装を呼び出す
}
}
……
//デフォルト実装の競合解決例
var stoppableVehicle2 = StoppableVehicle2()
stoppableVehicle2.stop() //「Original stop implementation!Stopped slowly...Stopped suddenly!!!」
このサンプルでは「Stoppable」インタフェースと「Stoppable2」インタフェースで同名の「stop」というメソッドが両方ともデフォルト実装を持ち、名前が競合しています。通常インタフェースにデフォルト実装があれば、インタフェースを実装したクラスでそのメソッドをオーバーライドしなくても問題ありませんが、名前が競合している場合は、このサンプルのように、明示的にメソッドをオーバーライドする必要があります。
ここでは、「StoppableVehicle2」クラスでstopメソッドを明示的にオーバーライドし、その中でsuperキーワードを使って2つのインタフェースのデフォルト実装を呼び出しています。「super<インタフェース名>.メソッド名()」とすることで、実装しているインタフェースのうち、呼び出すインタフェースを指定できます*2。
*2)Java 8でもデフォルト実装のために競合解決が必要ですが、同様のケースでJavaで呼び出すインタフェースを指定する場合は「インタフェース名.super.メソッド名()」となる点が少し異なります。
デフォルト実装によってインタフェースの活用範囲が広がりますが、このような競合解決の必要性も出てきますので、使用に際してはメリット、デメリットを考慮したいですね。
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
Kotlin(プログラミング言語)
Kotlin(コトリン)は「実用的」であることを主眼においたプログラミング言語だ。その特徴は簡潔/安全/汎用/(Javaとの)相互運用性にある。
JVMとAndroid用のオープンソースプログラミング言語「Kotlin 1.0」がリリース
JetBrainsが主導して開発を進めるJVMとAndroid用のオープンソースプログラミング言語の正式版がリリース。既存のコードやインフラとの相互運用性を重視した実用的なプログラミング言語だという。
2017年プログラミング言語別平均年収ランキング、1位は「Scala」 平均626万円
ビズリーチは、「プログラミング言語別 平均年収ランキング2017」を発表した。第1位はScalaで平均年収は626万円、第2位はPythonで601万円、第3位はKotlinで577万円だった。SwiftやRuby、Javaなどもランクインした。