回答:
システム(自分自身を含む)で作業する開発者に、作成するクラスに一連のメソッドを実装するように強制する場合は、インターフェースを使用します。
お使いのシステムで作業する開発者を強制したいとき、抽象クラスを使用してメソッドのセット番号を実装するために(自分を含む)と、あなたは彼らの子クラスを開発するのに役立ちますいくつかの基本メソッドを提供したいです。
留意すべきもう1つの点は、クライアントクラスは1つの抽象クラスしか拡張できないのに対し、クライアントクラスは複数のインターフェースを実装できることです。したがって、抽象クラスで動作コントラクトを定義している場合、つまり、各子クラスは単一のコントラクトにのみ準拠することができます。ユーザープログラマーを特定のパスに沿って強制したい場合、これは良いことです。時にはそれは悪いでしょう。PHPのCountableおよびIteratorインターフェースがインターフェースではなく抽象クラスであると想像してください。
どちらに進むかが不明な場合によくあるアプローチの1つは(以下のcletusで説明されているように)、インターフェイスを作成し、抽象クラスにそのインターフェイスを実装させることです。
an Abstract Class
とan の違いInterface
:
抽象クラス
抽象クラスはいくつかの機能を提供し、残りを派生クラスに任せることができます。
派生クラスは、基本クラスで定義された具象関数をオーバーライドする場合とオーバーライドしない場合があります。
抽象クラスから拡張された子クラスは、論理的に関連付けられている必要があります。
インターフェース
インターフェイスに機能を含めることはできません。それは唯一の方法の定義が含まれています。
派生クラスは、インターフェイスで定義されたすべてのメソッドのコードを提供する必要があります。
完全に異なる関連のないクラスは、インターフェースを使用して論理的にグループ化できます。
abstract class X implements Y
とは class X implements Y
どう違いますか?
abstract class X implements Y
、Xのバルク機能を派生クラスに実装し、抽象クラスと派生クラスの両方にYで定義された関数を含める必要があることを宣言しますclass X implements Y
が、クラスXにはYで定義された関数を含める必要があることだけを意味します。は、XIが実際にインターフェースとしてのYの定義をスキップし、Yの関数をpublic / protected / private抽象関数として実装するだけで、派生クラスに実装されていることを確認する以外のクラスによって実装されることを意図していません。
なぜ抽象クラスを使用するのですか?以下は簡単な例です。次のコードがあるとします。
<?php
class Fruit {
private $color;
public function eat() {
// chew
}
public function setColor($c) {
$this->color = $c;
}
}
class Apple extends Fruit {
public function eat() {
// chew until core
}
}
class Orange extends Fruit {
public function eat() {
// peeling
// chew
}
}
今、私はあなたにリンゴを与え、あなたはそれを食べます。どんな味?りんごの味です。
<?php
$apple = new Apple();
$apple->eat();
// Now I give you a fruit.
$fruit = new Fruit();
$fruit->eat();
それはどんな味ですか?まあ、それはあまり意味がありませんので、あなたはそれをすることができないはずです。これは、Fruitクラスを抽象化し、その内部にeatメソッドを作成することで実現されます。
<?php
abstract class Fruit {
private $color;
abstract public function eat(){}
public function setColor($c) {
$this->color = $c;
}
}
?>
抽象クラスはインターフェイスに似ていますが、メソッドは抽象クラスで定義できますが、インターフェイスではすべて抽象です。抽象クラスには、空のメソッドと作業/コンクリートメソッドの両方を含めることができます。インターフェースでは、そこで定義された関数に本体を含めることはできません。抽象クラスでは可能です。
実際の例:
<?php
abstract class person {
public $LastName;
public $FirstName;
public $BirthDate;
abstract protected function write_info();
}
final class employee extends person{
public $EmployeeNumber;
public $DateHired;
public function write_info(){
//sql codes here
echo "Writing ". $this->LastName . "'s info to emloyee dbase table <br>";
}
}
final class student extends person{
public $StudentNumber;
public $CourseName;
public function write_info(){
//sql codes here
echo "Writing ". $this->LastName . "'s info to student dbase table <br>";
}
}
///----------
$personA = new employee;
$personB = new student;
$personA->FirstName="Joe";
$personA->LastName="Sbody";
$personB->FirstName="Ben";
$personB->LastName="Dover";
$personA->write_info();
// Writing Sbody's info to emloyee dbase table
$personB->write_info();
// Writing Dover's info to student dbase table
What does that taste like? Well, it doesn't make much sense, so you shouldn't be able to do that.
私は抽象を知っています!
final
キーワードは何をしますか?投稿ありがとうございます。
これをミックスに投入するだけですが、Cletusが抽象クラスと組み合わせてインターフェースを使用することを述べたように、私はしばしばインターフェースを使用して、私のデザイン思考を明確にします。
例えば:
<?php
class parser implements parserDecoratorPattern {
//...
}
このようにして、私のコードを読んでいる人(およびデコレータパターンが何であるかを知っている人)は、a)パーサーの構築方法とb)デコレータパターンの実装に使用されているメソッドを確認できます。
また、ここではJava / C ++ / etcプログラマーではないので、データタイプが関係する場合があります。あなたのオブジェクトはタイプであり、あなたがそれらをタイプの周りに渡すとき、プログラム的に重要です。収縮可能な項目をインターフェイスに移動すると、メソッドが返す型が決まるだけで、それを実装するクラスの基本型は決まりません。
遅いですし、より良い擬似コードの例を考えることはできませんが、ここに行きます:
<?php
interface TelevisionControls {};
class Remote implements TelevisionControls {};
class Spouse implements TelevisionControls {};
Spouse spouse = new Spouse();
Remote remote = new Remote();
isSameType = (bool)(remote == spouse)
また、ここで付け加えておきたいのは、他のオブジェクト指向言語にはなんらかの種類のインターフェースがあり、抽象化も、PHPと同じ意味と目的があるということではありません。抽象化/インターフェースの使い方は少し異なりますが、PHPのインターフェースには実際には実際の機能はありません。それらは単に意味論的およびスキーム関連の理由で使用されます。重要なのは、将来の開発者がまったく異なる使用計画を持っているかどうかに関係なく、プロジェクトをできるだけ柔軟で拡張可能で、将来の拡張に対して安全にすることです。
英語が母国語でない場合は、抽象化とインターフェースが実際に何であるかを検索する可能性があります。そして、同義語も探してください。
そして、これは比喩としてあなたを助けるかもしれません:
インターフェース
たとえば、イチゴで新しい種類のケーキを焼いて、材料と手順を説明するレシピを作成したとします。なぜそれがそんなに美味しいのか、そしてあなたのゲストがそれを好むのはあなただけです。次に、他の人もそのケーキを試すことができるように、レシピを公開することにしました。
ここでのポイントは
-それを正しくするために
-注意
すること-(イチゴが多すぎるなど)悪化する可能性があることを防ぐため
-それを試してみる人が簡単にできるようにすること
-何をすべきか(攪拌のような時間)を伝えること)
-実行できるが、実行してはいけないことを伝える
まさにこれがインターフェースを説明するものです。これはガイドであり、レシピの内容を観察するための一連の指示です。PHPでプロジェクトを作成し、GitHubまたは仲間などでコードを提供する場合と同じです。インターフェースは、人々ができることとすべきでないことです。それを保持するルール-あなたがそれに従わない場合、全体の構造が壊れます。
抽象化
ここでこの比喩を続けます...想像してみてください、あなたは今回、そのケーキを食べるゲストです。次に、レシピを使用してそのケーキを試します。ただし、新しい材料を追加したり、レシピに記載されている手順を変更またはスキップしたりする必要があります。それでは次に何が来るのでしょうか?そのケーキの別のバージョンを計画します。今回はイチゴではなくブラックベリーとバニラクリームを加えた...おいしい。
これは、元のケーキの拡張と考えることができるものです。基本的には新しいレシピを作成することで抽象化を行います。いくつかの新しいステップとその他の要素があります。ただし、ブラックベリーバージョンには、元のバージョンから引き継いだいくつかの部分があります。これらは、あらゆる種類のケーキに必要な基本ステップです。まるで牛乳のように材料のように-それはすべての派生クラスにあるものです
今、あなたは材料とステップを交換したいと思っています、そしてこれらはそのケーキの新しいバージョンで定義されなければなりません。これらは新しいケーキのために定義されなければならない抽象的なメソッドです、なぜならケーキに果物があるはずですが、どれですか?今回はブラックベリーを取ります。できました。
これで、あなたはケーキを拡張し、インターフェースに従い、そこからステップと成分を抽象化しました。
すでに優れた答えのいくつかに追加するには:
抽象クラスを使用すると、ある程度の実装を提供できます。インターフェースは純粋なテンプレートです。インターフェイスは機能のみを定義でき、実装することはできません。
インターフェースを実装するクラスは、それが定義するすべてのメソッドの実装をコミットするか、抽象的に宣言する必要があります。
インターフェースは、JavaのようにPHPが多重継承をサポートしないという事実を管理するのに役立ちます。PHPクラスは、単一の親のみを拡張できます。ただし、必要な数のインターフェイスを実装することをクラスに約束することができます。
type:実装するインターフェースごとに、クラスは対応する型をとります。どのクラスも1つ(または複数の)インターフェースを実装できるため、インターフェースは事実上、関係のない型を効果的に結合します。
クラスは、スーパークラスを拡張し、任意の数のインターフェースを実装できます。
class SubClass extends ParentClass implements Interface1, Interface2 {
// ...
}
いつインターフェースを使用する必要があるのか、いつ抽象クラスを使用する必要があるのか説明してください。
これまで何も実装されていないテンプレートのみを提供する必要があり、そのインターフェースを実装するクラスが、それを実装する他のクラスと同じメソッドを持つようにする場合は、インターフェースを使用します。
他のオブジェクト(部分的に構築されたクラス)の基盤を作成する場合は、抽象クラスを使用します。抽象クラスを拡張するクラスは、定義/実装されたいくつかのプロパティまたはメソッドを使用します。
<?php
// interface
class X implements Y { } // this is saying that "X" agrees to speak language "Y" with your code.
// abstract class
class X extends Y { } // this is saying that "X" is going to complete the partial class "Y".
?>
抽象クラスをインターフェイスに変更するにはどうすればよいですか?
簡略化したケース/例を以下に示します。実装の詳細を取り出します。たとえば、抽象クラスを次のように変更します。
abstract class ClassToBuildUpon {
public function doSomething() {
echo 'Did something.';
}
}
に:
interface ClassToBuildUpon {
public function doSomething();
}
物理学の観点から:
抽象クラスは「ある」関係を表します。果物があるとしましょう。よくある責任と行動を共有する果物抽象クラスがあります。
インターフェイスは「すべき」関係を表します。私の意見では、インターフェース(ジュニア開発者の意見です)は、アクションまたはアクションに近いものによって名前を付ける必要があります(申し訳ありませんが、単語を見つけることができません。英語のネイティブスピーカーではありません)。 IEatableとしましょう。あなたはそれが食べられることを知っています、しかしあなたはあなたが何を食べるか知りません。
コーディングの観点から:
オブジェクトに重複したコードがある場合、それらは共通の動作を持っていることを示しています。つまり、コードを再利用するには抽象クラスが必要になる可能性があり、インターフェイスでは実行できません。
もう1つの違いは、オブジェクトは必要な数のインターフェイスを実装できることですが、「ダイヤモンドの問題」のため、1つの抽象クラスしか持てません(理由はこちらをチェックしてください。http://en.wikipedia.org/wiki/ Multiple_inheritance#The_diamond_problem)
たぶんいくつかのポイントは忘れてしまいますが、はっきりさせていただければと思います。
PS: "is a" / "should do"はVivek Vermaniの答えによってもたらされました。私は彼の答えを盗むつもりはありませんでした。私がそれらを気に入ったので、単に用語を再利用するためです!
抽象クラスとインターフェースの技術的な違いは、すでに他の回答に正確にリストされています。オブジェクト指向プログラミングのためにコードを書く際に、クラスとインターフェースのどちらかを選択するための説明を追加したいと思います。
クラスはエンティティを表す必要がありますが、インターフェースは動作を表す必要があります。
例を見てみましょう。コンピュータモニタはエンティティであり、クラスとして表す必要があります。
class Monitor{
private int monitorNo;
}
ディスプレイインターフェイスを提供するように設計されているため、機能はインターフェイスで定義する必要があります。
interface Display{
void display();
}
他の回答で説明されているように、他にも考慮すべきことがたくさんありますが、これはコーディング中にほとんどの人が無視する最も基本的なことです。
PHP
両方を使用する必要がある場合の例を追加したかっただけです。現在、汎用ERPソリューションでデータベースモデルにバインドされたファイルハンドラーを作成しています。
このようにして、異なるファイル用の複数のテンプレートと、明確に区別されたインターフェースメソッドの共通セットを用意します。このインターフェースは、基本の抽象クラスの場合とは異なり、アクセスメソッドに類似しています。
将来、さまざまなファイルストレージサービス用のアダプタを作成するときに、この実装により、インターフェイスをまったく異なるコンテキストで他の場所で使用できるようになります。
abstract
とinterface
クラスの使用法を理解するために一日中試みていました、あなたの投稿はそれをすべて明らかにしました。