言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

Kotlin辞典

  1. トップページ
  2. Kotlin辞典
  3. open / override

open / override

対応: Kotlin 1.0(2016)

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.メソッド()スーパークラスのメソッドを呼び出します。

サンプルコード

sample_main.kt
// 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("Red", 4.0, 3.0),
        Square("Blue", 5.0),
        Circle("Green", 3.0)
    )

    shapes.forEach { printInfo(it) }

    println()

    // super を使ってスーパークラスのメソッドを呼び出す
    val rect = Rectangle("Yellow", 6.0, 2.0)
    println(rect.describe())  // super.describe() が含まれる
}

実行結果

sample_open_override.kt
Red の図形、面積: 12.00(長方形 4.0×3.0)
  周囲: 14.00
Blue の正方形、一辺: 5.0、面積: 25.00
  周囲: 20.00
Green の図形、面積: 28.27
  周囲: 18.85
Yellow の図形、面積: 12.00(長方形 6.0×2.0)
open_override.kt
kotlinc open_override.kt -include-runtime -d open_override.jar
java -jar open_override.jar
Red の図形、面積: 12.00(長方形 4.0×3.0)
  周囲: 14.00
Blue の正方形、一辺: 5.0、面積: 25.00
  周囲: 20.00
Green の図形、面積: 28.27
  周囲: 18.85
Yellow の図形、面積: 12.00(長方形 6.0×2.0)

概要

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

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

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

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