Kotlinの抽象クラス・インターフェースの違いと使い分けを初心者向けにやさしく解説!
生徒
「Kotlinで“抽象クラス”とか“インターフェース”って出てきましたけど、何が違うんですか?」
先生
「それはKotlinのクラス設計でとても重要なポイントです。両方とも“共通のルール”を決めるものですが、使い方や目的が少し違うんですよ。」
生徒
「具体的にどんな時に使い分ければいいんでしょうか?」
先生
「では、Kotlinの抽象クラスとインターフェースについて、特徴と違いを一緒に見ていきましょう!」
1. 抽象クラスとは?Kotlinでの基本
Kotlinの抽象クラス(abstract class)とは、「共通の機能や動きをまとめておくけれど、そのままでは使えないクラス」のことです。あくまで“設計図”のような存在で、実際に動かすには子クラスで具体的な中身を書き足します。
たとえば「動物」という大きなグループを考えると、どの動物も眠りますが、鳴き方は動物ごとに違いますよね。このとき、「眠る」処理は共通で、「鳴く」処理だけそれぞれの動物に任せるような形が抽象クラスです。
abstract class Animal {
// 鳴き方は動物によって違うので、中身は書かずに約束だけ
abstract fun makeSound()
// 眠る動作は共通なので、そのまま使える
fun sleep() {
println("眠っています")
}
}
抽象クラスのポイントは、abstractを付けた関数には中身がないこと。これが「設計図だけがある状態」です。実際に使うには、子クラスで具体的な処理を必ず書く必要があります。
もう少しイメージしやすい例を見てみましょう。
class Cat : Animal() {
override fun makeSound() {
println("ニャーと鳴いています")
}
}
fun main() {
val cat = Cat()
cat.makeSound() // 子クラスで作った処理
cat.sleep() // 親クラスの共通機能
}
ニャーと鳴いています
眠っています
このように、抽象クラスは「共通の機能を持ちつつ、部分的に子クラスへ任せる」ために使われます。コードを整理しやすくなるので、Kotlinでしっかり覚えておきたい仕組みです。
2. 抽象クラスを継承して使う
抽象クラスを使うには、それを継承した子クラスで、abstractな関数をoverrideして実装します。
class Dog : Animal() {
override fun makeSound() {
println("ワンワン!")
}
}
fun main() {
val dog = Dog()
dog.makeSound()
dog.sleep()
}
ワンワン!
眠っています
makeSound()は子クラスで定義し直していますが、sleep()は親クラスのまま使えます。
3. インターフェースとは?Kotlinでの基本
インターフェース(interface)も、「クラスに必要な機能のルール」を決めるしくみです。
ただし、インターフェースには「状態(プロパティ)」を持たせることができず、「機能(関数)」だけを決めるのが基本です。
簡単に言えば「やり方だけを約束する契約書」です。
interface Flyable {
fun fly()
}
4. インターフェースの実装方法
インターフェースを使いたいクラスは:を使ってinterfaceを「実装」します。
class Bird : Flyable {
override fun fly() {
println("パタパタ飛んでいます")
}
}
fun main() {
val bird = Bird()
bird.fly()
}
パタパタ飛んでいます
インターフェースの関数は必ずoverrideで実装しないといけません。
5. 抽象クラスとインターフェースの違い
ここで、Kotlinの抽象クラスとインターフェースの違いを整理しておきましょう。
- 抽象クラスは「機能(関数)」と「状態(プロパティ)」の両方を持てる。
- インターフェースは主に「やるべきこと(関数)」だけを書く。
- クラスは1つの抽象クラスしか継承できないが、インターフェースは複数実装できる。
6. インターフェースの複数実装ができる例
Kotlinでは、インターフェースをいくつも同時に実装できます。
interface Walkable {
fun walk()
}
class Human : Walkable, Flyable {
override fun walk() {
println("歩いています")
}
override fun fly() {
println("想像の中で飛んでいます")
}
}
fun main() {
val person = Human()
person.walk()
person.fly()
}
歩いています
想像の中で飛んでいます
このように、WalkableとFlyableという2つのインターフェースを同時に使えます。
7. どちらを使うべき?使い分けのポイント
Kotlinで抽象クラスとインターフェースを使い分けるときは、次のようなポイントで判断します。
- 共通のプロパティ(状態)を持たせたい → 抽象クラス
- 複数の動作ルールを柔軟に追加したい → インターフェース
- 他のクラスをすでに継承している → インターフェース(多重継承が可能だから)
どちらも「共通ルール」を決めるためのものですが、役割と使い方が少しずつ違います。
8. 抽象クラスとインターフェースの使い方を身近な例で
例えば、「家電」という抽象クラスがあり、共通で電源を入れる関数とメーカー名という情報があるとします。
一方、「ネット接続できる機能」はどんな家電でも持てるように、インターフェースとして用意します。
abstract class Appliance(val brand: String) {
abstract fun turnOn()
}
interface NetworkCapable {
fun connectToWifi()
}
class SmartTV(brand: String) : Appliance(brand), NetworkCapable {
override fun turnOn() {
println("$brandのテレビを起動します")
}
override fun connectToWifi() {
println("Wi-Fiに接続しました")
}
}
fun main() {
val tv = SmartTV("ソニー")
tv.turnOn()
tv.connectToWifi()
}
ソニーのテレビを起動します
Wi-Fiに接続しました
このように、抽象クラスとインターフェースを組み合わせることで、柔軟で分かりやすい設計ができます。
まとめ
Kotlinのクラス設計において、「抽象クラス」と「インターフェース」は非常に重要なキーワードです。今回の記事では、それぞれの役割や違い、使い分けの考え方を初心者向けにやさしく解説しました。
抽象クラスは、共通する処理や状態(プロパティ)を持ちつつ、子クラスで処理内容を具体的に実装させたいときに使います。一方でインターフェースは、「何ができるか」という動作(関数)のルールだけを定めたいときに利用します。つまり、抽象クラス=共通の設計図+機能実装、インターフェース=行動の契約書と覚えておくとわかりやすいです。
特にKotlinでは、クラスはひとつの抽象クラスしか継承できませんが、インターフェースは複数同時に実装できるという特徴があるため、柔軟な設計が求められる現場ではよく併用されます。以下は、抽象クラスとインターフェースを組み合わせた実践的なコード例です。
abstract class Vehicle(val name: String) {
abstract fun start()
fun stop() {
println("$name を停止します")
}
}
interface Electric {
fun charge()
}
class EVCar(name: String) : Vehicle(name), Electric {
override fun start() {
println("$name のエンジンを起動します")
}
override fun charge() {
println("$name を充電中です")
}
}
fun main() {
val tesla = EVCar("テスラ")
tesla.start()
tesla.charge()
tesla.stop()
}
テスラ のエンジンを起動します
テスラ を充電中です
テスラ を停止します
このように、抽象クラスによって共通の処理(startやstopなど)を提供し、インターフェースによって追加の動作(charge)を柔軟に定義できる設計は、現実のアプリ開発でも多く見られます。
プログラミング初心者のうちは、「継承って難しい」「overrideって何?」と感じるかもしれませんが、動物や乗り物、家電などの例でイメージをつかみながら学ぶと理解しやすくなります。また、「プロパティが必要なら抽象クラス」「動作だけならインターフェース」といった判断基準を持っておくと、設計の幅がぐっと広がります。
Kotlinでオブジェクト指向を学ぶには、まずこの2つの違いと使い方をしっかり理解することが大切です。今回の内容をもとに、実際のプロジェクトでも応用してみてください。
生徒
「抽象クラスとインターフェースって、どちらも似てるけど、使い方がぜんぜん違うんですね。」
先生
「そうです。共通する動きや状態をまとめたいなら抽象クラス、行動のルールだけを決めたいならインターフェースが向いていますよ。」
生徒
「あと、インターフェースは複数同時に使えるのが便利ですね!家電とか乗り物の例がとてもわかりやすかったです。」
先生
「その調子です。設計力をつけるには、こうした基本をしっかり理解しておくことが大切です。今後は実際にコードで書いてみるともっと理解が深まりますよ。」
生徒
「はい!次は自分でも抽象クラスとインターフェースを組み合わせて何か作ってみます!」
先生
「とてもいいですね。練習を重ねることで、自然に使い分けができるようになりますよ。」