Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

Kotlin辞典

open / override

Kotlinのクラスはデフォルトで継承不可(final)です。継承を許可するには『open』を付けます。サブクラスでメソッドを上書きするには『override』を使います。抽象クラスは『abstract』で定義します。

構文
// open を付けたクラスは継承できます。
open class Animal(val name: String) {
    open fun sound(): String = "..."  // open で override 可能にします。
    fun breathe() = println("呼吸します")  // open なし = override 不可
}

// サブクラスで override します。
class Dog(name: String) : Animal(name) {
    override fun sound(): String = "ワン!"
}

// abstract クラス(インスタンス生成不可)
abstract class Shape {
    abstract fun area(): Double  // サブクラスで必ず実装が必要です。
    fun describe() = println("図形です")  // 具体的なメソッドも持てます。
}
構文一覧
修飾子概要
open class継承を許可するクラスです(デフォルトは final)。
open funサブクラスで override できるメソッドです。
override funスーパークラスのメソッドを上書きします。
final override funこれ以上の override を禁止します。
abstract class / funインスタンス生成不可のクラス、必ず実装が必要なメソッドです。
super.メソッド()スーパークラスのメソッドを呼び出します。
サンプルコード
// abstract クラスで共通の振る舞いを定義します。
abstract class Shape(val color: String) {
    abstract fun area(): Double
    abstract fun perimeter(): Double
    open fun describe() = "$color の図形、面積: ${"%.2f".format(area())}"
}

// open クラスで継承します。
open class Rectangle(color: String, val width: Double, val height: Double) : Shape(color) {
    override fun area() = width * height
    override fun perimeter() = 2 * (width + height)
    override fun describe() = super.describe() + "(長方形 ${width}×${height})"
}

// Rectangle をさらに継承します(open が必要)
class Square(color: String, val side: Double) : Rectangle(color, side, side) {
    // final override — これ以上の override を禁止します。
    final override fun describe() = "$color の正方形、一辺: $side、面積: ${"%.2f".format(area())}"
}

class Circle(color: String, val radius: Double) : Shape(color) {
    override fun area() = Math.PI * radius * radius
    override fun perimeter() = 2 * Math.PI * radius
}

fun printInfo(shape: Shape) {
    println(shape.describe())
    println("  周囲: ${"%.2f".format(shape.perimeter())}")
}

fun main() {
    val shapes: List<Shape> = listOf(
        Rectangle("赤", 4.0, 3.0),
        Square("青", 5.0),
        Circle("緑", 3.0)
    )

    shapes.forEach { printInfo(it) }

    println()

    // super を使ってスーパークラスのメソッドを呼び出します。
    val rect = Rectangle("黄", 6.0, 2.0)
    println(rect.describe())  // super.describe() が含まれます。
}
実行結果
赤 の図形、面積: 12.00(長方形 4.0×3.0)
  周囲: 14.00
青 の正方形、一辺: 5.0、面積: 25.00
  周囲: 20.00
緑 の図形、面積: 28.27
  周囲: 18.85
黄 の図形、面積: 12.00(長方形 6.0×2.0)
概要

Kotlinが「デフォルトfinal」を採用しているのは、意図しない継承によるバグを防ぐためです。継承を使う場合は明示的に『open』を付ける必要があり、設計の意図が明確になります。

『abstract』は「このメソッドはサブクラスで必ず実装してください」という契約です。実装を強制するためインターフェースに似ていますが、状態(フィールド)を持てる点が異なります。インターフェースとの使い分けは、共通の状態を持つ基底クラスは abstract class、型の契約のみならば interfaceを選ぶと良いでしょう。

インターフェースの定義はinterfaceを、クラスの基本はclass / コンストラクターを参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。