Javaを学び始めた頃、if文やfor文がそれっぽく動くようになってきて、 「お!自分、ちょっと書けるかも?」と気分が上がった時期がありました。
ところがその矢先、設計に関する章で現れた2つの言葉――
抽象クラスとインターフェース
読めるけどわからない。 構文は理解できるようになったのに、急に「設計の哲学」みたいな話になって、
「この2人…どこがどう違うの?そもそも何に使うの?」
と、思考が一時停止した覚えがあります。
しかも、どちらも“継承っぽい”し、“実装っぽい”し、
「じゃあ何が違うのよ~!」
と心の中で叫びながらググり続けた初心者時代…。
この記事では、そんな私の「よくわからなかった思い出」を振り返りつつ、 Java設計の柱である「抽象クラス」と「インターフェース」の違いと使い分けについて、 初心者の方でもスッと理解できるようにお伝えしていきます。
最後まで読めば、「使い分けってそういうことか!」とすっきり整理できるはずです。 それでは一緒に、Java設計の迷路を抜けていきましょう!
似てるようで全然違う?Java設計の2大柱に出会う
「どっちが何なの…?」と頭がこんがらがった日々
Javaの文法が少しずつ理解できるようになってきた頃。 if文やforループ、メソッドやクラスの書き方も手になじんできて、 「もしかしてプログラミング、ちょっと分かってきたかも…?」と自信が芽生えたその時。
本に現れた2つの強そうな単語。
抽象クラス(abstract class) インターフェース(interface)
…え?なにそれ?どっちも似てる名前だけど、どう違うの? そもそも、これっていつ使うの?
“理解できそうでできない”感じにモヤモヤして、ググったページの説明もまた抽象的で、
「あ〜もうちょっと優しく教えてくれ〜!」
と叫びたくなったのを、私は今でも覚えています。
Java設計には“型”の使い方が肝になる!
クラスを使ってコードを整理できるようになると、 次に求められるのは「どんな型で設計するか?」という力です。
具体的には、こういう疑問が生まれてきます
- 複数のクラスに共通する機能をまとめたいけど、どう設計する?
- 実装は子クラスに任せたいけど、呼び出し側からは共通の扱いをしたい
- 「これは〇〇という役割を持つものです」と言えるようにしたい
こうした“設計の選択”の中核になるのが、抽象クラスとインターフェースなのです。
両者が登場する理由:「共通点」と「役割」を表すため
Javaでは、いろんなクラスが登場してきます。 その中で「この子たち、似てるところあるよね?」とか「この子たち、〇〇できるって言えそうだよね?」という場面が出てきます。
- 抽象クラス → 「共通のベースをまとめたい」
- インターフェース → 「〇〇できるもの」として扱いたい
このように、“まとめるか”“役割を与えるか”で使い分けるのが基本です。
どちらも「直接は使えない型」であり、実装は子に任せる!
両者とも、設計時に「直接 new できない」制約があります
abstract class Animal {
abstract void speak();
}
interface Walkable {
void walk();
}
このように、“設計図としての型”であり、「実装は子クラスに任せるよ」という立ち位置なのが共通点です。
でも、構文も特徴も、よく見るとまるで違う。
だからこそ、次章からはまず 抽象クラスの特徴と使い方をじっくり見ていきます。
「共通点をまとめる」とはどういうことなのか、実例と一緒に理解していきましょう!
抽象クラス入門:共通の土台を“ちょっと残す”選択肢
「抽象クラス」って何が抽象的なの?
「abstract class」を初めて見たときの違和感って、今でも覚えています。
「クラスなのにnewできない?」「メソッドに中身がない?」 という状態、もはやコードなのかポエムなのか、理解が追いつかず…。
でも実は、抽象クラスは“共通のベース”を作るための便利な型なんです。
たとえば、「動物には共通する性質があるけど、鳴き方はそれぞれ違う」みたいな場面にピッタリ。
例:動物たちの共通の土台を作ってみよう
// 抽象クラスの定義
public abstract class Animal {
void eat() {
System.out.println("もぐもぐ食べる");
}
abstract void speak(); // 実装は子に任せる
}
この Animal クラスは「すべての動物が食べる」という共通点を持ちながら、 「鳴き方はそれぞれ違うよね?」という点は 抽象メソッド(中身なし) にして、 具体的な実装はサブクラスに委ねているんです。
public class Dog extends Animal {
@Override
void speak() {
System.out.println("ワンワン!");
}
}
このように、一部だけ共通化して“ちょっと抽象的に残しておく”ことで、設計が柔軟になります。
抽象クラスは直接newできない
抽象クラスは、実体を持たない設計図のようなもの。
だから、こんなコードはエラーになります
Animal a = new Animal(); // ❌ エラー!抽象クラスは直接インスタンス化できない
使いたいなら、具象(具体的な)クラスを作って継承する必要があります
Animal a = new Dog(); // ⭕️ OK!DogはAnimalの実装を持っている
抽象クラスの特徴まとめ
特徴 | 内容 |
---|---|
継承のためのクラス | 親クラスとして機能する。サブクラスで拡張する前提 |
一部だけ実装 | 共通の処理は書き、差分は抽象メソッドにして任せる |
インスタンス不可 | newできない。あくまで“設計図”として機能する |
このように、「似てるけど、全部一緒ではない」クラスたちの共通点をまとめるのが抽象クラスの真骨頂です。
設計のねらい:「土台は親に、振る舞いは子に」
抽象クラスを使うと、設計が自然になります
- 繰り返し同じ処理を書く必要がない
- 子クラスに“個性”を持たせられる
- 拡張性がある、でもベースは守れる
まるで、「型はそろってるけど、使い方は自由」のような道具箱。
Javaの設計って、実はけっこうオシャレなんです。
インターフェース入門:「〜できる」役割を表す設計
「インターフェース」って、何かの入口なの…?
Javaで interface という単語を見たとき、私は「インターフェースって、画面の入り口みたいなやつ…?」と勘違いしてました…。
実はJavaのインターフェースは、「クラスに〇〇できる役割を持たせる仕組み」のことなんです。
例えば、あるクラスが「歩ける」なら Walkable、 「飛べる」なら Flyable のように、行動や機能ベースで設計できるのがインターフェースの魅力。
ここからは、そんな“できる”を表すインターフェースの基本と使い方を見ていきましょう!
例:「歩ける」っていう役割だけを与えてみよう
// インターフェースの定義
public interface Walkable {
void walk(); // 実装なし!あくまでルールだけ
}
この Walkable は、「このクラスには walk() が必要だよ」という約束を表しています。
実際の処理は、このインターフェースを“実装する”クラスにお任せ
public class Dog implements Walkable {
@Override
public void walk() {
System.out.println("わんこがてくてく歩く!");
}
}
こうして、“〜できる”という役割を付与しつつ、実装は自由に決められる設計が完成します。
インターフェースの基本ルール
特徴 | 内容 |
---|---|
実装(implements)で使う | 継承じゃなくて「実装」。ルールを守るという意味に近い |
メソッドは実装なし | インターフェース内のメソッドには処理を書かない |
複数のインターフェース可 | ひとつのクラスがいくつも実装できる(多重継承OK!) |
Javaではクラスの継承は1つだけしかできませんが、インターフェースは複数同時に実装可能
public interface Swimable { void swim(); }
public class Penguin implements Walkable, Swimable {
@Override
public void walk() { System.out.println("ぺたぺた…"); }
@Override
public void swim() { System.out.println("スイスイ〜"); }
}
このように、「〇〇できる」機能を組み合わせて設計できるのがインターフェースの強みです。
Java8以降の「defaultメソッド」って何?
Java8からは、インターフェース内に default を使って、「初期実装あり」のメソッドが書けるようになりました
public interface Greeting {
default void sayHello() {
System.out.println("こんにちは!");
}
}
これは「基本的な挨拶はみんな共通だけど、必要ならオーバーライドしてカスタマイズしてもいいよ〜」という考え方。
ただし、あまり使いすぎると「インターフェースなのに実装だらけ!」という状態になるので、シンプルさを失わないよう注意が必要です。
インターフェースの設計視点:「役割の表現」に特化する!
インターフェースは「〜できる」や「〜するもの」という“行動・能力の定義”に向いています
- Flyable → 飛べるもの
- Readable → 読めるもの
- Comparable → 比較できるもの
このように、「クラスの本質とは別の軸で行動を持たせたいとき」に、インターフェースが大活躍します。
この章のまとめ
- インターフェースは “〇〇できる”という役割・機能を定義する型
- 実装(implements)を使って、クラス側で処理を書く
- 複数のインターフェースを組み合わせて、柔軟な設計が可能
- defaultメソッドの追加で、共通処理もほどよくまとめられる
次章では、抽象クラスとインターフェースの違いをズバッと比較して、 「じゃあ、結局どっちを使えばいいの?」という疑問にお答えしていきます。
こう違う!抽象クラスとインターフェースの比較早見表
「どっちも似てるようで、よく見るとルールが違う…?」
抽象クラスとインターフェース、これまでの章でそれぞれを理解してきましたが…いざ設計に使うとなると、
「どっちでもできそうだけど、どう選ぶの?」 「使える場面はかぶってない?」
という疑問が出てくる方も多いはず。
この章では、仕様や特徴を徹底比較しながら、使い分けのポイントを整理していきます。
仕様の違いを比較表で整理!
項目 | 抽象クラス(abstract class) | インターフェース(interface) |
---|---|---|
継承・実装方法 | extends | implements |
継承できる数 | 1つだけ(単一継承) | 複数可能(多重実装) |
フィールドの定義 | OK(普通の変数を持てる) | ×(定数のみ。static final になる) |
メソッドの中身 | あり(普通のメソッドも持てる) | なし(ただし、defaultで実装可 ※Java8以降) |
抽象メソッド | 定義できる。abstract をつけて宣言 | 全部が抽象的(Java8より前) |
コンストラクタ | 定義できる | 定義できない(newできない) |
用途のイメージ | “共通の土台”を持つ型 | “役割を与える”型 |
実例で見比べてみよう
抽象クラス:共通処理+個別実装
public abstract class Animal {
void eat() {
System.out.println("もぐもぐ食べる");
}
abstract void speak(); // 子に任せる
}
インターフェース:行動定義のみ
public interface Flyable {
void fly(); // 行動だけ定義する
}
どちらも「直接 new できない」「子クラス側で実装が必要」という点では似てますが、役割と設計意図がまったく違うんです。
Java8以降で少しルールが変わった!
Java8以降では、インターフェースに default メソッドが追加されました
public interface Greeting {
default void sayHello() {
System.out.println("こんにちは!");
}
}
これにより「ちょっとだけ共通処理も入れたいな〜」というケースに対応できるようになりました。
とはいえ、defaultメソッドを入れすぎると「これ…もう抽象クラスでいいのでは?」という事態になるので注意。
設計視点:この違いをどう使い分ける?
抽象クラス
→ 「〇〇は△△の一種である(is-a)」という関係があるときに使う → 共通のコード(フィールドやロジック)をまとめたいときに便利
インターフェース
→ 「〇〇できる(can-do)」という能力・役割を表現したいときに使う → クラスの設計に“機能”を組み合わせたいときに便利(多重実装OK!)
まとめ:違いを知れば、設計はもっと自由になる!
抽象クラスとインターフェース、それぞれが持つ特徴は一長一短。
どっちが優れているかではなく、「どんな場面で使えば心地よく設計できるか?」が大切です。
次章では、実際に「迷ったときどうする?」という判断ポイントにフォーカスして、 「どっちを選べばいいの?」という悩みにやさしく答えていきます。
どっちを使う?迷ったときの判断ポイント3つ
「抽象クラスとインターフェース、結局どっちがいいの?」
ここまで読んでくださった方の中には、こんなモヤモヤを感じている方もいるかもしれません。
どっちも便利そうだけど、使うタイミングってどう見極めるの? 設計時に正解があるなら、それを教えてほしい!
正直なところ、設計には明確な“正解”はありません。
でも、判断に迷ったときに役立つ3つの考え方があります。
判断ポイント①:「is-a」か「can-do」かで関係性を見極める
まずは設計対象の関係性を考えてみましょう。
- Dog is an Animal → 継承でOK(抽象クラス)
- Penguin can swim → インターフェースが自然(Swimable)
使い分けイメージ
関係性 | 設計アプローチ |
---|---|
is-a | 抽象クラスでまとめる |
can-do | インターフェースで役割付与 |
この見分け方は、「クラスの本質と機能を分けて考える」のにとても役立ちます!
判断ポイント②:「共通の処理があるかどうか」をチェックする
設計するクラスに、共通のフィールドやロジックがあるなら抽象クラスが向いています。
一方、動き(メソッド)だけ定義したい場合はインターフェースが最適
例:動物の設計
- 全員が eat() を持っていて、コードも共通 → 抽象クラス
- それぞれが「泳ぐ」「飛ぶ」など役割を持っている → インターフェース
つまり、「コードを再利用したいのか、共通ルールだけ決めたいのか」で選ぶのがポイントです。
判断ポイント③:拡張性と柔軟性のバランス
設計が長く使われる前提なら、変化に強い設計が大切になります。
- 抽象クラスは1つしか継承できない → 構造が固定されやすい
- インターフェースは複数実装できる → 機能を組み合わせやすい
特に「外部ライブラリに依存したくない」「将来的に動きを追加したい」などの場合は、インターフェースで柔軟に設計しておくと安心です。
組み合わせもあり!ハイブリッド設計のすすめ
実は、両者を組み合わせて使うこともできます
public abstract class Animal implements Walkable {
abstract void speak();
@Override
public void walk() {
System.out.println("てくてく歩く");
}
}
このように、「共通処理は抽象クラス」「機能追加はインターフェース」という設計の分業スタイルもおすすめです。
この章のまとめ
- 「is-a」なら抽象クラス、「can-do」ならインターフェースが基本
- 共通のロジックを持たせたいときは抽象クラス
- 柔軟な拡張性が欲しいならインターフェース
- 両者の“得意な役割”を活かして、ハイブリッド設計も可能!
次章では、ここまでの知識を振り返りつつ、 「これでJava設計がぐっと身近になった!」と思えるようにまとめていきます。
まとめ:役割と共通点、どう抽象化して設計するか?
設計とは、「どんな型で語るか」を選ぶこと
抽象クラスとインターフェース。どちらも“抽象化”という言葉で説明されますが、実はその意味は少し違います。
- 抽象クラス:似ている部分をまとめて「共通の土台」として抽象化する
- インターフェース:「できること(機能)」に注目して、役割を抽象化する
この違いを知ることで、Java設計はただの構文の組み合わせではなく、「考え方」の表現であることが見えてきます。
設計の選び方に迷ったら、「問い方」を変えてみよう
- このクラスは〇〇の一種だろうか? → 抽象クラスの出番かも
- このクラスに〇〇できる能力を持たせたい? → インターフェースが合ってるかも
- 将来的にこの設計は拡張・変更しやすい? → 柔軟性の面から再検討しよう
こうした“問いの投げかけ”ができるようになると、設計の選択に自分の意思と根拠が持てるようになります。
設計とは、つくる前の「準備」と「想像」の時間
Javaのコードは書いて動かすだけではありません。
- どうすれば変更しやすいか?
- 誰が読んでもすぐ理解できるか?
- 使う人の“期待”に応えられているか?
設計とは、こうした未来を想像しながら型を選ぶ「準備の時間」なんです。
抽象クラスとインターフェースは、そんな想像をカタチにするための道具。
今日からできる一歩:「なぜこの設計にしたか?」を書いてみる
もしクラスを作るときに迷ったら、ぜひコメントやメモに「この設計にした理由」を書いてみてください
// Animalを抽象クラスにした理由:eat()を共通処理とし、鳴き方は個性として子に任せたいから
この小さな一行が、未来の自分や他の人への最高のドキュメントになります。
そして何より、「自分は設計に向き合った」と思える、ちょっとした誇りにもなるはずです。
次に学びたいテーマは?
設計の楽しさが少しでも伝わったなら、次はこんなテーマがおすすめです
- 依存性の注入(DI):柔軟でテストしやすい設計ってどう書く?
- SOLID原則:オブジェクト指向設計の“迷わない指針”って何?
- デザインパターン入門:ありがちな問題をスマートに解決する定番テクニック
今日の学びが、明日書くコードを少し心地よくする。
この記事がその一歩になれたなら、書いた私としてはそれ以上に嬉しいことはありません。

Javaの構文を覚えたあと、「設計って何?」と戸惑ったあの日の私へ。 抽象クラスとインターフェース――聞き慣れない言葉たちに頭がこんがらがっても、 少しずつ「意味」だけでなく「使いどころ」まで見えてくる瞬間があります。
この記事が、そんな“設計の迷路”を少しでも明るくできたなら、それがいちばん嬉しいです。コードを書くことは、自分の考えを形にすること。 そして、設計とはその考え方に理由と秩序を与えること。
今日の学びは、きっとこれからの設計にちいさな自信をくれるはずです。 読んでくれたあなたが、次にコードを書くとき、少しだけ気持ちよくなれるように―― そんな願いを込めて、この記事を届けました。
また一緒にJavaの世界を探検していきましょう!

設計ってむずかしそうだったけど、少しずつ仲良くなれてる気がするの。たぶん、きっと、うん。
コメント