詳しく分かりやすい説明をしてくれてるサイトが多いので、もはや、下記サイトをご覧になっていただければ済む話ですが、一応、自分なりにインターフェイス(interface)と抽象(abstract)クラスの違いを調べました。(ほぼ、他サイト様の流用です。)
⇩ インターフェイスと抽象クラスについては下記サイトへ
・[PHP] abstractとinterfaceの使い分けを整理してみる | Suinasia
・PHPのオブジェクト指向入門 | オブジェクト指向PHP.NET
・【 ほでなすPHP 】 PHP5の基本 - > インターフェイス
・PHPのinterfaceとabstractを正しく理解して使い分けたいぞー ::ハブろぐ
まずは、それぞれの特徴を書き出します。
インターフェイス(interface)の特徴
- キーワードinterfaceにより定義します。
- 通常のクラスと 同様に定義することができますが、メソッドの実装は全く定義されません。
- インターフェイス内で宣言される全てのメソッドはpublicである必要があります。(インターフェイスの特性によります。抽象メソッドのみ記述可能。自動でpublic abstractとなってるらしいです。つまり、抽象メソッドしか定義できない。)
- 変数(プロパティ)は持てません。
- インターフェイスに定数を持たせることはできます。
(インターフェイス定数は クラス定数 とまったく同じように動作します。
しかし、 そのインターフェイスを継承したクラスやインターフェイスから上書きすることはできません。) - インターフェイスを実装するには、implements 演算子を使用します。
(クラスにimplementsされないとウドの大木。クラスの存在が必要不可欠。) - インターフェイスに含まれる全てのメソッドを実装する必要があります。
(implements先のクラスでメソッドはオーバーライドされる必要がある。) - 各インターフェイスをカンマで区切って指定することで、 クラスは複数のインターフェイスを実装することができます。
- クラスと同様、インターフェイスも extends 演算子で継承することができます。
- インターフェイスを実装したクラスには、 そのインターフェイスで定義されているメソッドとまったく同じシグネチャを持つメソッドが必要です。
メソッドの実装とは(Javaでの説明なので、PHPでも当てはまるか分かりません。)
メソッドの「本体」。
メソッドの宣言直後にある{ }で囲まれた箇所を「メソッドの実装」と呼びます。
また、インターフェイスのメソッドには実装がないため、インターフェイスからimplementsすることも「インターフェイスから実装する」と言いいます。
またそのクラスを「インターフェイスの実装クラス」と言いいます。
そして、インターフェイスのメソッドを「オーバーライド」することも「実装する」と言いいます。
インターフェイスのメソッドは宣言のみのため、そこに「実装を追加する」からです。
と言っても、一般的には「オーバーライドした」と言うことの方が多いです。
「定義」とほぼ同意。
ですが、インターフェイスのメソッドを「定義する」とはあまり言いいません。
一応「オーバーライド」のことを「再定義」と呼ぶことはあります。
implements
〈…に〉道具[手段]を与える。
《プログラムに機能を》 インプリメントする, 実装する。
抽象クラス(abstract)の特徴
- キーワードabstractで定義します。
- abstractとして定義されたクラスのインスタンスを生成することはできません。
(継承された子クラスでインスタンス化が可能。) - 1つ以上の抽象メソッドを含む全てのクラスもまた抽象クラスとなります。
- abstractとして定義されたメソッドは、そのメソッドの外観を宣言するのみで、 実装を定義することはできません。
- abstract以外のメソッドは、実装を定義できます。
- 抽象クラスから継承する際、親クラスの宣言で abstract としてマークされた 全てのメソッドは、子クラスで定義されなければなりません。
(メソッドは子クラスでオーバーライドされる必要がある。) - これらのメソッドは同等 (あるいはより緩い制約) の可視性(アクセス権) で定義される必要があります。
(※例えば、抽象メソッドが protected として定義された場合、その関数の実装は protected または public のどちらかとして定義する必要があります。
private にすることはできません。) - メソッドのシグネチャも必ず一致していなくてはなりません。 すなわち、型ヒントや必須引数の数についても同じでなければならないということです。
キーワードのリスト
これらのキーワードは、PHP では特別な意味があります。
これらのいくつかは 関数やメソッドのようなものを表し、いくつかは定数のようなものを表す、 といったようになっていますが、実際にはそうではありません。
実際には、 これらは言語を構成するものです。
以下のキーワードはいずれも定数、クラス名、 関数名として使用することはできません。
これらを変数名として使用することは一般的には可能ですが、 混乱を生じる可能性があります。
__halt_compiler() | abstract | and | array() | as |
break | callable(PHP 5.4 以降) | case | catch | class |
clone | const | continue | declare | default |
die() | do | echo | else | elseif |
empty() | enddeclare | endfor | endforeach | endif |
endswitch | endwhile | eval() | exit() | extends |
final | finally(PHP 5.5 以降) | for | foreach | function |
global | goto (PHP 5.3 以降) | if | implements | include |
include_once | instanceof | insteadof(PHP 5.4 以降) | interface | isset() |
list() | namespace(PHP 5.3 以降) | new | or | |
private | protected | public | require | require_once |
return | static | switch | throw | trait (PHP 5.4 以降) |
try | unset() | use | var | while |
xor | yield (PHP 5.5 以降) |
__CLASS__ | __DIR__(PHP 5.3 以降) | __FILE__ | __FUNCTION__ | __LINE__ | __METHOD__ |
__NAMESPACE__(PHP 5.3 以降) | __TRAIT__(PHP 5.4 以降) |
継承の決まり事としてPHP: クラスの基礎 - Manual の説明によると
extends
クラスは、宣言部に extends キーワードを含めることで、他のクラスのメソッドと プロパティを継承することができます。
多重継承を行うことはできず、クラスが継承できるベース クラスは一つだけです。
継承されたメソッドやプロパティをオーバーライドするには、 親クラスで定義されているのと同じ名前でそれを再宣言します。
しかし、親クラスでそのメソッドが final 定義されている場合はオーバーライドできません。
オーバーライドされた元のメソッドや静的プロパティにアクセスするには、 parent:: で参照します。
メソッドをオーバーライドするときには、パラメータのシグネチャも同じでなければなりません。
もし違っていれば、PHP はE_STRICT
レベルのエラーとなります。
ただしコンストラクタは例外で、 異なるパラメータでオーバーライドすることができます。
ISA(is-a)関係とCAN DO関係(Javaで言われてたことなのでPHPで成り立つのか分かりません)
クラスの継承(例: 抽象クラスと派生クラスの「継承」の関係)は ISA関係
A extends B
A は Bの一種と見なせる
----
インタフェースの実装(例:インターフェイスと実装クラスの「実装」の関係)は CAN DO関係
A implements B
A は Bのメソッドが実行できる
⇩ 詳しくは下記PDF情報で。(内容がJavaっぽいんで、PHPにも当てはまるかは分かりません。)
プログラミングⅡ 第12回 ---- オブジェクト指向型 プログラミング パラダイム
is-a
知識表現、オブジェクト指向プログラミング、オブジェクト指向設計では、is-aとは、あるクラスBはもう一つのクラスAのサブクラスである(また、AはBのスーパークラスである)という関係である。
言い換えれば、"BはAである"は通常、概念Bは概念Aの特化であり、概念Aは概念Bの汎化であることを意味する。
例として、「フルーツ」は「リンゴ」、「オレンジ」、「マンゴー」などの汎化である。
リンゴはフルーツである(is-a) (Apple is a fruit.)と言える。
オブジェクト指向プログラミングではis-a関係は継承という概念の中で使われる。
たとえばリンゴは、「果肉に種が入った植物」に属するというような、フルーツすべてに共通するプロパティをすべて継承するといって差し支えない。
is-a関係とは、異なる種類の階層の性質をもつ関係にhas-aがある。
オブジェクトと従属するオブジェクトの論理関係がis-aか、それともhas-aなのか、いつもはっきりと決定できるものではない。
この曖昧さが、is-aのようなメタ言語的な用語を生み出した。
インターフェイス(interface)、抽象(abstract)クラス共に単体では動けず
インターフェイスは、何かしらのクラスにimplementsされることで実装され、
抽象クラスは、自身以外のクラスに継承されないと動きださないようです。
他人がいないと成り立たない、まさに小判鮫みたいな感じでしょうか。
メソッドの内容(実装の定義)は派遣先で決められる
しかも、あろうことか、このインターフェイスと抽象クラスのお二方は、派遣先(実装・継承された先)のクラスにメソッドの内容を決めさせ(オーバーライドする)、更にこのメソッドを必ず実行するように強要するそうです。
なんか、嫌な感じなひとにしかみえないっす。
インターフェイスはいくつでも実装できるし、継承もできる
クラスが多重継承できないのに対し、インターフェイスはいくつでも盛り込めるようです。
しかも、インターフェイスは、クラスのようにインターフェイス同士の継承が可能。
インターフェイスはクラス使用者のために、抽象クラスはクラス設計者のために
抽象クラス
抽象クラスはあくまで複数のクラスの共通部分を抽出して一つのクラスとし、 処理の中身は違うけど(継承先の子クラスで定義されるまで抽象メソッドの実装は決まらない)必ず必要なメソッドは抽象メソッドとして定義し、 各クラスはこの抽象クラスを継承して独自の処理は勝手に作ってねってということらしいです。
クラス設計を楽にする、言ってみれば抽象メソッドはクラス設計者向けの仕組み。
インターフェイスを実装しているクラスは、そのインターフェイスで定義されているメソッドが存在することを保証しています。(インターフェイスに含まれる全てのメソッドはimplements先のクラスで実装される必要があるため。)
インターフェイスのメソッドは、implements先のクラスで実装が定義されるので、普通だったらクラスで定義されてるメソッドの実装を確認したい時に、クラスを探して確認しなければいけませんが、その必要がなくなります。
インターフェイスはクラス使用者向けの仕組み。
結論
インターフェイスも抽象クラスも、最初は嫌なひとという印象でしたが、クラス設計者・使用者を助けてくれる立派なしくみだったんですね。
使いこなせるように勉強していかねばです。