Kotlinの継承とインターフェース:オブジェクト指向設計の実践【Kotlin入門⑤】

継承とは?

継承(Inheritance)は、既存のクラスを拡張し、新しいクラスを作成するためのオブジェクト指向の重要な概念です。Kotlinでは、クラスの再利用性を高めるために継承を活用します。

Kotlinにおける継承の基本

Kotlinでは、クラスはデフォルトでfinalとなっており、継承可能にするにはopenキーワードを付ける必要があります。

open class Animal(val name: String) {
    open fun makeSound() {
        println("Some generic animal sound")
    }
}

class Dog(name: String) : Animal(name) {
    override fun makeSound() {
        println("Woof Woof!")
    }
}

fun main() {
    val dog = Dog("Buddy")
    dog.makeSound() // 出力: Woof Woof!
}

この例では、AnimalクラスをDogクラスが継承し、makeSoundメソッドをオーバーライドしています。

オーバーライドとsuperキーワード

メソッドのオーバーライド

親クラスのメソッドを子クラスで再定義する場合、overrideキーワードを使用します。

open class Bird {
    open fun fly() {
        println("Bird is flying")
    }
}

class Eagle : Bird() {
    override fun fly() {
        println("Eagle soars high in the sky")
    }
}

superキーワードの使用

superキーワードを使うことで、親クラスのメソッドを呼び出すことができます。

open class Vehicle {
    open fun start() {
        println("Vehicle is starting")
    }
}

class Car : Vehicle() {
    override fun start() {
        super.start()
        println("Car is starting")
    }
}

fun main() {
    val myCar = Car()
    myCar.start()
}

この例では、super.start()を使うことで、親クラスVehiclestartメソッドを実行した後に、子クラスの処理を追加しています。

抽象クラス(Abstract Class)

抽象クラスとは?

抽象クラスは、インスタンス化できないクラスであり、共通の機能を提供するために使用されます。

abstract class Animal(val name: String) {
    abstract fun makeSound()
}

class Cat(name: String) : Animal(name) {
    override fun makeSound() {
        println("Meow Meow!")
    }
}

fun main() {
    val cat = Cat("Kitty")
    cat.makeSound()
}

抽象クラスでは、abstractキーワードを使用してメソッドを定義し、子クラスで実装する必要があります。

インターフェース(Interface)

インターフェースの基本

インターフェースは、異なるクラスに共通の機能を持たせるために使用されます。Kotlinのインターフェースには、interfaceキーワードを使用します。

interface Drivable {
    fun drive()
}

class Bicycle : Drivable {
    override fun drive() {
        println("Bicycle is moving")
    }
}

fun main() {
    val bike = Bicycle()
    bike.drive()
}

複数のインターフェースを実装する

Kotlinでは、1つのクラスが複数のインターフェースを実装することができます。

interface Movable {
    fun move()
}

interface Flyable {
    fun fly()
}

class Airplane : Movable, Flyable {
    override fun move() {
        println("Airplane is moving on the runway")
    }
    
    override fun fly() {
        println("Airplane is flying in the sky")
    }
}

fun main() {
    val airplane = Airplane()
    airplane.move()
    airplane.fly()
}

インターフェースのデフォルト実装

Kotlinのインターフェースには、デフォルトの実装を持たせることができます。

interface Printable {
    fun printMessage() {
        println("Printing message")
    }
}

class Document : Printable

fun main() {
    val doc = Document()
    doc.printMessage() // 出力: Printing message
}

デフォルト実装を持つことで、各クラスが独自に実装する手間を省くことができます。

まとめ

本記事では、Kotlinにおける継承とインターフェースの基本について詳しく解説しました。Kotlinの継承機能を活用することで、コードの再利用性を高め、インターフェースを使うことで異なるクラス間で共通の機能を持たせることができます。