ここでは、Kotlin におけるオブジェクト指向についてまとめます。
オブジェクトを生成する方法、インターフェイス、クラスの役割について理解が深まります。
特に、インターフェイスの概念は、Kotlin や Android アプリで有用です。
オブジェクト式
Kotlin でオブジェクトを生成するには、キーワード object を使用します。
object のブロック内では、変数や関数(メソッド)を定義できます。
燃料(gas)という変数を持つ車(car)というオブジェクトを生成してみます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
fun main() { val car = object { // 燃料 var gas: Int = 10 // 給油する fun fill(liter: Int) { gas += liter } // 走行する fun run(liter: Int) { gas -= liter } // 残燃料を表示 fun showRemainingGas() { println(gas) } } car.showRemainingGas() // 10 car.fill(10) car.showRemainingGas() // 20 car.run(5) car.showRemainingGas() // 15 } |
ポイント
Kotlin では、キーワード object によるオブジェクトの生成方法をオブジェクト式と呼びます。
データ型とインターフェイスの実装
Kotlin でオブジェクトを生成する方法を紹介しましたが、このままでは使えません。
なぜなら、データ型を持っていないため、2台の車などを同じ定義で扱うことができません。
データ型を定義する interface(インターフェイス)
オブジェクトのデータ型を定義するには、interface を使用します。
|
1 2 3 4 5 6 7 8 9 |
interface Car fun main() { val car = object : Car { // (略) } // (略) } |
interface Car と記述して Car というデータ型のインターフェイスを定義しています。
object を生成する時に、コロン「:」 を付けてインターフェースを記述することで、
生成されるオブジェクトが、指定したインターフェイスを実装していることを明示しています。
提供するメソッドをインターフェイスにまとめる
インターフェイスと呼ばれるからには、外部とのやり取りを規定する必要があります。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
interface Car { fun fill(liter: Int) fun run(liter: Int) fun getRemainingGas(): Int } fun main() { val car = object : Car { // 燃料 var gas: Int = 10 // 給油する override fun fill(liter: Int) { gas += liter } // 走行する override fun run(liter: Int) { gas -= liter } // 残燃料を取得 override fun getRemainingGas(): Int = gas } println("${car.getRemainingGas()}") // 10 car.fill(10) println("${car.getRemainingGas()}") // 20 car.run(5) println("${car.getRemainingGas()}") // 15 } |
インターフェイス Car に、オブジェクトが提供すべきメソッドをまとめています。
それを上書き(修飾子:override)する形で実装し、データ型 Car を持つオブジェクトを生成します。
オブジェクトのインスタンス
データ型を持つオブジェクトを生成できるようになれば、インスタンスとして扱えるようになります。
例えば、「車1」と「車2」のように、同じインターフェイスを持つオブジェクトを複数生成できます。
複数生成するために、Car というデータ型を持つオブジェクトを生成する関数を用意します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
interface Car { fun fill(liter: Int) fun run(liter: Int) fun getRemainingGas(): Int } fun createCar(): Car = object : Car { // 燃料 var gas: Int = 10 // 給油する override fun fill(liter: Int) { gas += liter } // 走行する override fun run(liter: Int) { gas -= liter } // 残燃料を取得 override fun getRemainingGas(): Int = gas } fun main() { val car1 = createCar() val car2 = createCar() println("${car1.getRemainingGas()}") // 10 println("${car2.getRemainingGas()}") // 10 car1.fill(10) println("${car1.getRemainingGas()}") // 20 println("${car2.getRemainingGas()}") // 10 } |
車1と車2が異なる残燃料を示していることから、
Car というデータ型のオブジェクトが複数生成できたことが分かります。
クラス
オブジェクト式によるオブジェクトの生成方法を紹介しましたが、クラスのコンストラクタ(constructor)を呼出すことで、クラスに定義したメソッドやプロパティの実装を持つオブジェクトを生成できます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
interface Car { // (略) } class CarImpl() : Car { // (略) } fun main() { val car1 = CarImpl() val car2 = CarImpl() // (略) } |
キーワード class とクラス名を記述することで、クラスを定義することができます。
クラス名を記述して変数に代入することで、CarImpl クラスのオブジェクトを生成しています。
※Impl は Implementation(実装)の略で、インターフェイスの実装クラス名の末尾に付けることが多い。
まとめ
- キーワード object を使ったオブジェクト式で、オブジェクトの実装・生成ができる
- インターフェイスを定義することで、オブジェクトに「型」を与える
- インターフェイスには、実装すべきメソッドやプロパティを宣言
- クラスを定義すると、簡単にオブジェクトを生成できる