はじめに
オブジェクト指向プログラミングにおいて 抽象 (abstract) は、
「共通の振る舞いはまとめつつ、一部の実装はサブクラスに任せる」ための仕組みです。
Kotlin では abstract キーワードを使います。
1. 抽象クラスとは?
-
abstract classは インスタンス化できないクラス - 1つ以上の 抽象メソッド (実装なしのメソッド) を持てる
- 共通処理(具象メソッド)も定義できる
例
abstract class Animal(val name: String) {
abstract fun speak() // 抽象メソッド(実装必須)
fun introduce() {
println("私は $name です")
}
}
class Dog(name: String) : Animal(name) {
override fun speak() {
println("ワンワン!")
}
}
val dog = Dog("ポチ")
dog.introduce() // 私は ポチ です
dog.speak() // ワンワン!
Animal は直接インスタンス化できませんが、Dog が抽象メソッドを実装することで使えるようになります。
2. 抽象メソッドと抽象プロパティ
- 抽象メソッド:本体を持たず、サブクラスで必ず実装する
- 抽象プロパティ:getter/setter をサブクラスで必ず実装する
abstract class Shape {
abstract val area: Double
abstract fun draw()
}
class Circle(val radius: Double) : Shape() {
override val area: Double get() = Math.PI * radius * radius
override fun draw() = println("半径 $radius の円を描く")
}
val circle = Circle(5.0)
println(circle.area) // 78.5398...
circle.draw() // 半径 5.0 の円を描く
プロパティも abstract にできる点は、インターフェースと似ています。
3. abstract と open の違い
-
abstract- 実装を持たず、サブクラスで必ずオーバーライドしなければならない
- 暗黙的に
open(オーバーライド可能)
-
open- 実装を持っているが、サブクラスでオーバーライドできる
- 実装は任意
比較例
abstract class Base {
abstract fun mustImplement() // 強制実装
open fun mayOverride() {} // 任意でオーバーライド可能
fun cannotOverride() {} // final(デフォルト)
}
4. 抽象クラス vs インターフェース
| 項目 | 抽象クラス | インターフェース |
|---|---|---|
| 多重継承 | 不可 | 可能 |
| フィールド保持 | 可能 | 不可(プロパティ定義は可能だが状態は持てない) |
| コンストラクタ | 持てる | 持てない |
| 用途 | 共通処理+状態を共有したい場合 | 契約(仕様)を定義したい場合 |
Kotlin では インターフェース+デフォルト実装 が使えるので、
Java よりもインターフェースの活躍が多くなります。
5. まとめ
-
abstract classは直接インスタンス化できない - 抽象メソッド・抽象プロパティはサブクラスで必ず実装が必要
-
abstractは暗黙的にopen - 「状態を持たせたい」なら抽象クラス、「仕様だけ定義したい」ならインターフェース