PHPのinterfaceと抽象クラスの違いを初心者向けにやさしく解説!
生徒
「PHPのインターフェースとか抽象クラスって、何が違うんですか?初心者にはややこしく感じます…」
先生
「たしかに最初は混乱しやすいですね。でも、それぞれの特徴をきちんと理解すれば使い分けもできるようになりますよ!」
生徒
「たとえばどんなときにinterfaceを使って、どんなときにabstract classを使えばいいんですか?」
先生
「よし、今日はPHPのinterfaceと抽象クラスの違いを、図やたとえも使いながら、わかりやすく説明していきましょう!」
1. interface(インターフェース)とは?
PHPのinterface(インターフェース)は、一言でいうと「そのクラスが必ず持っていなければならない機能(メソッド)」を約束するための設計書です。
最大の特徴は、インターフェースの中には「具体的な処理(どう動くか)」を一切書かないことです。「どんな名前のメソッドが必要か」というルールだけを定義します。
たとえば、プログラミング未経験の方なら「家電の操作」をイメージしてみましょう。テレビでもエアコンでも、メーカーが違っても「電源を入れる」「電源を切る」という操作(ルール)は共通ですよね。この「共通の操作ルール」がインターフェースにあたります。
以下のサンプルコードは、移動できるもの(Movable)というルールを作った例です。
interface Movable {
// 「歩く」という機能が必要!というルール
public function walk();
// 「止まる」という機能が必要!というルール
public function stop();
}
このように定義しておくことで、このMovableというインターフェースを使うすべてのクラス(人間、ロボット、動物など)に対して、「必ずwalkとstopというメソッドを中身まで含めて作ってくださいね」と強制することができます。
もし、このルールに従ったクラスで「walk」を作り忘れると、PHPが「ルール違反ですよ!」とエラーを出して教えてくれるため、多人数での開発や大規模なプログラムでもミスを防ぐことができるのです。
2. 抽象クラス(abstract class)とは?
PHPのabstract class(抽象クラス)は、インターフェースと同じように「クラスの形(メソッド)」を強制する役割を持ちますが、「共通の処理(中身)」をあらかじめ書いておけるという大きな違いがあります。
例えるなら、抽象クラスは「半分くらい完成しているプラモデルの設計図」です。「どのパーツもタイヤは4つ必要(共通)」という決まりと、「ボディの色や形は作る人が決めてね(未完成)」という部分が混ざっている状態です。
プログラミング未経験の方なら、「動物」というグループをイメージしてみてください。「名前を登録する」という機能はどの動物も同じですが、「鳴き声」は動物の種類によって違いますよね。そういった「共通部分」と「個別のルール」をセットで定義できるのが抽象クラスの強みです。
// 抽象クラス「Animal」を定義
abstract class Animal {
public $name;
// 共通の処理:名前をセットする機能(どの動物も共通)
public function setName($name) {
$this->name = $name;
echo $this->name . "という名前に決まりました!<br>";
}
// 抽象メソッド:鳴く機能(中身は空っぽで、後で必ず作るというルール)
abstract public function speak();
}
このようにabstractキーワードをつけて定義したメソッドは、そのクラスを継承(利用)する側で必ず中身をプログラミングしなければならないという強力な制約になります。
「共通する便利な機能は再利用しつつ、絶対に守ってほしいルールも設定したい」という場面で、抽象クラスは非常に役立ちます。これにより、プログラムの記述量を減らしながら、バグの少ない安全なコードを書くことが可能になります。
3. interfaceとabstract classの違いを表で比較
インターフェースと抽象クラスはどちらも「クラスの設計図」としての役割を持ちますが、その性質は大きく異なります。まずは、それぞれの違いを一覧表で整理してみましょう。
| 比較ポイント | interface(インターフェース) | abstract class(抽象クラス) |
|---|---|---|
| 処理の中身(実装) | 一切書けない 「何をするか」の名前だけ定義 |
一部書ける 共通の処理を具体的に記述可能 |
| プロパティ(変数) | 持てない 定数のみ定義可能 |
持てる 名前や数値などのデータを保持できる |
| 継承・実装の数 | 複数可能(多重実装) 「,」で区切っていくつでも使える |
1つだけ(単一継承) 1つのクラスからしか引き継げない |
| 役割のイメージ | 「交換可能な部品」の規格 USB規格やコンセントの形など |
「未完成のベースモデル」 基本機能付きのテンプレート |
より具体的にイメージするために、プログラミング未経験の方でもわかりやすい「スマートフォンの機能」を例に挙げたサンプルコードを見てみましょう。
【具体例:充電機能とOSの基本動作】
・充電(Chargeable)は「共通のルール」なのでインターフェース
・OS(BasePhone)は「共通の画面表示」などの中身を持つので抽象クラス
// インターフェース:充電できるものなら何でも守るべきルール
interface Chargeable {
public function connectCable(); // ケーブルを差すというルール
}
// 抽象クラス:スマートフォンの共通の土台
abstract class BasePhone {
// 共通のプロパティ(変数)
public $batteryPercent = 50;
// 共通の処理(中身がある)
public function showScreen() {
echo "画面を表示します。現在の電池残量は " . $this->batteryPercent . "% です。<br>";
}
// 抽象メソッド(ルールだけ決めて、中身は機種ごとに任せる)
abstract public function unlock();
}
このように、interfaceは「その機能を持っていること」を証明するライセンスのような役割を果たし、abstract classは「基本的な機能は準備しておくから、足りない部分だけ作ってね」という親切なテンプレートのような役割を果たします。
この2つの違いを使い分けることで、コードの重複を減らしつつ、後から機能を追加しやすい「メンテナンス性の高いプログラム」を組むことができるようになります。
4. interfaceの実装(implements)方法
interfaceは、implementsキーワードでクラスに取り入れます。ルール通りに、すべてのメソッドを必ず作る必要があります。
interface Printer {
public function printData();
}
class PDFPrinter implements Printer {
public function printData() {
echo "PDFとして印刷します";
}
}
5. 抽象クラスの継承(extends)方法
抽象クラスは、extendsキーワードでクラスに継承します。共通部分はそのまま使えますが、abstractなメソッドは必ず作らないといけません。
abstract class Vehicle {
abstract public function run();
public function stop() {
echo "止まりました";
}
}
class Car extends Vehicle {
public function run() {
echo "車が走ります";
}
}
6. interfaceとabstract classを両方使う例
実際の開発では、interfaceとabstract classを組み合わせることもよくあります。interfaceでルールを決め、abstract classで共通機能を持たせる使い方です。
interface Flyable {
public function fly();
}
abstract class Bird {
public function layEggs() {
echo "卵を産みました";
}
}
class Eagle extends Bird implements Flyable {
public function fly() {
echo "高く飛びます";
}
}
このように、複数の性質を持たせるときにとても便利です。
7. interfaceとabstract classの使い分けのコツ
初心者が迷いがちな「どっちを使えばいいの?」というポイントについて、簡単な判断基準を紹介します。
- 「ルールだけ決めたい」→ interface
- 「共通の機能も持たせたい」→ abstract class
たとえば、いろんな種類のプリンタを作るとき、印刷ルールだけ決めたいならinterface。印刷処理の中で一部を共通にしたいならabstract classを使いましょう。
8. よくある初心者のつまずきポイント
interfaceとabstract classを使いこなすには、以下のような注意点も押さえておきましょう。
interfaceはメソッドの定義だけなので、処理を書いてはいけませんabstractクラスの抽象メソッドは、必ず子クラスで作る必要があります- 複数のinterfaceを
,でつなげて実装できます(例:implements A, B)
まとめ
interfaceとabstract classの違いを振り返る
ここまでPHPにおけるinterfaceとabstract classの違いについて解説してきましたが、あらためて整理すると、interfaceは「メソッドの定義だけを持つルール」、abstract classは「共通処理とルールの両方を持てる設計」と理解することが重要です。特に初心者の方は、この違いを曖昧なままにしてしまうと、オブジェクト指向設計で混乱しやすくなります。
interfaceは実装を持たないため、クラスごとに自由な実装が可能です。一方で、abstract classは共通処理をまとめて管理できるため、重複コードの削減や保守性の向上につながります。この違いは、実務の開発において非常に重要なポイントとなります。
PHPのオブジェクト指向設計における活用ポイント
PHPのオブジェクト指向プログラミングでは、interfaceとabstract classを適切に使い分けることで、柔軟で拡張性の高い設計が実現できます。たとえば、外部仕様として「必ずこの機能を持つ」という契約を定義したい場合はinterfaceが適しています。一方で、複数のクラスで共通する処理や状態をまとめたい場合はabstract classが効果的です。
また、interfaceは複数実装できるという特徴があるため、異なる機能を組み合わせる設計に向いています。これにより、複雑なシステムでも柔軟に機能追加が可能になります。abstract classは単一継承という制約があるものの、基本となる振る舞いを統一できる点が強みです。
サンプルプログラムで理解を深める
最後に、interfaceとabstract classを組み合わせた実践的なサンプルコードを確認してみましょう。実際の開発では、このように役割を分担して設計することが多くなります。
interface Loggable {
public function log($message);
}
abstract class BaseService {
protected $serviceName;
public function setServiceName($name) {
$this->serviceName = $name;
}
public function commonProcess() {
echo "共通処理を実行中";
}
abstract public function execute();
}
class UserService extends BaseService implements Loggable {
public function execute() {
echo "ユーザー処理を実行";
}
public function log($message) {
echo "ログ出力: " . $message;
}
}
このように、interfaceでログ出力のルールを定義し、abstract classで共通処理をまとめることで、読みやすく拡張しやすいコードを書くことができます。PHP開発ではこの設計パターンが頻繁に使われるため、しっかりと理解しておくと大きな武器になります。
初心者が意識したい重要ポイント
interfaceとabstract classの使い分けで迷ったときは、「ルールだけ必要か」「共通処理も必要か」を基準に考えると判断しやすくなります。また、最初はabstract classだけで設計してしまいがちですが、拡張性を考えるとinterfaceを積極的に使う意識も大切です。
特にチーム開発では、interfaceによって仕様を明確にすることで、他の開発者との認識ズレを防ぐことができます。結果として、バグの減少や開発効率の向上にもつながります。
本記事で解説した内容を理解しておくことで、PHPのオブジェクト指向設計に対する理解が深まり、より実践的なコードを書けるようになります。interfaceとabstract classは一見似ているようで役割が異なるため、それぞれの特徴を意識しながら使い分けていきましょう。
生徒
「interfaceはルールだけを決めるもので、abstract classは共通処理も書けるっていう違いが大事なんですね!」
先生
「その通りです。特に、複数のクラスで同じルールを守らせたいときはinterfaceが便利ですね。」
生徒
「abstract classは共通の処理をまとめたいときに使うんですよね?」
先生
「はい。たとえば同じような処理を何度も書く必要がある場合は、abstract classにまとめると効率的です。」
生徒
「両方を組み合わせることで、より柔軟な設計ができるのも理解できました!」
先生
「素晴らしいですね。その理解があれば、実務でもしっかり活かせますよ。これからは設計を意識してコードを書いてみてください。」