PHPにインターフェイスがあるのはなぜですか?


35

PHP5の時点で、言語にインターフェースが追加されていることに気付きました。ただし、PHPは非常に緩やかに型付けされているため、インターフェイスを使用する利点のほとんどが失われているようです。なぜこれが言語に含まれているのですか?


5
正しい質問はなぜだと思いますか?
アルベルトフェルナンデス

5
利点を提供していないように見えるので、なぜそれらを含めるのですか?
GSto

4
@HorusKolおよびそれらは実装される前は使用されていなかったため、以前のバージョンでは未使用で役に立たなかったことがわかります。また、それらの使用が何らかの形で改善されているという主張を、それらが有用であると言って支持しなければなりません。
ラインヘンリヒズ

6
@HorusKolまったくスペシャスではありません。ハンマーの価値提案を示すのは簡単です。この質問は、誰かが議論の仕方で価値があると宣言するだけでなく、PHPインターフェースの価値提案を実証するように求めています。
ラインヘンリッヒス

3
また、インターフェイスは入力だけではないことを忘れないでください。インターフェースは、実装するクラスレイアウトするメソッドを含める必要があることを示す契約です。プラグインエンジンなどに役立ちます。
マイケル

回答:


30

PHPのインターフェイスの主な利点は、クラスが複数のインターフェイスを実装できることです。これにより、いくつかの機能を共有するが、必ずしも親クラスを共有しないクラスをグループ化できます。いくつかの例には、特定の方法でのクラスのプロパティのキャッシュ、出力、またはアクセスが含まれます。

コードでは、クラス名を確認する代わりに、クラスが特定のインターフェイスを実装しているかどうかを確認できます。その後、新しいクラスが追加されてもコードは機能します。

PHPは、http//php.net/manual/en/reserved.interfaces.phpなど、さまざまな状況で役立ついくつかの事前定義されたインターフェースを提供します。

編集-サンプルの追加

MyInterfaceという名前のインターフェイスがあり、一部の機能を共有する場合と共有しない場合がある異なるクラスの複数のオブジェクトを操作している場合、インターフェイスを使用すると次のようなことができます。

// Assume $objects is an array of instances of various classes
foreach($objects as $obj) {
 if($obj instanceof MyInterface) {
     $obj->a();
     $obj->b();
     $obj->c();
   }
}

23
言い換えれば、「動的型付け言語のすべての利点を完全に無視することができます」
カミルトムシク

11
@Kamil、静的タイピングの利点を、不要な場合に欠点に悩まされることなく活用できると考えています。
カールビーレフェルト

9
真剣ですか?instanceof?if-then-if-then-if-then-the-the-the-time-the-the-the-time、それはおなじみに聞こえませんか?ああ、はい、手続き型プログラミング。
カミルトムシク

23
@KamilTomšíkPHPを無能に使用している人々ではなく、PHPの言語に対する別のin辱。PHPには、完全なオブジェクト指向プログラミングのためのすべてのツールがあります。それらを使用するかどうかはプログラマー次第です。さらに、手続き型プログラミング自体に問題はありません。
ロータスノーツ

18
@Kamil-あなたのコメントを読むことで、OOPにif-sがなく、何らかの形で魔法のように動作するという結論に達するかもしれません。ワオ。
マイケルJV

23

PHPは緩やかに型付けされていますが、メソッドパラメーターなどについて強く型付けできます。

次の例を考えてみましょう。

interface Car { function go(); }

class Porsche { function go() {} }

function drive(Car $car) {}

$porsche = new Porsche();

drive($porsche);

上記のコードは次を出力します:

drive()に渡される引数1は、インターフェイスCar、指定されたポルシェのインスタンスを実装する必要があります


1
確かに、それはあまりにも悪いです。nullただし、パラメータにデフォルト値を設定できます。
エマニュイルルセフ

5
ただし、driveが必要な場合は、とにかくCar渡すnullことはあまり役に立ちません
...-HorusKol

7
nullを渡さないでください。「特別なケース」オブジェクトを使用します(Martin Fowlerの説明のためにGoogle)。
マーティンブロア

2
@Renesisデフォルト値をnullに設定すると、nullをタイプヒントメソッドに渡すことができます。(CAR $ car = null)では、引数としてnullを使用してこのメ​​ソッドを呼び出すことができます。ただし、これはかなりばかげた方法です。一体どうしてそんなことをしたいのですか?
dqhendricks

2
具体的な例: function addView($name, Template $template, SecurityMode $securityMode = null, $methodName = null);がありますが$methodName、ありません$securityMode
ニコール

7

インターフェイスを使用すると、オープンクローズの原則を実装し、疎結合のコードベースを維持し、最高のOOPデザインパターンの多くを実装できます。

たとえば、あるクラスが別のクラスを引数として受け入れる場合:

class A {

    public function __construct(B $class_b) {
        // use class b
        $class_b->run();
    }
}

クラスAとクラスBは密結合になり、クラスAはB以外の他のクラスを使用できません。型のヒントにより、正しい型の引数があることが確認されますが、AとBの関係は強固になりました。

ただし、クラスAでrun()メソッドを持つすべてのタイプのクラスを使用できるようにしたいとします。これは基本的に(完全ではありませんが)コマンドデザインパターンです。解決するには、代わりに具体的なクラスの代わりにインターフェースを使用してヒントを入力します。Bは、そのインターフェイスを実装し、クラスAの引数として受け入れられます。このようにして、クラスAは、そのインターフェイスをコンストラクタの引数として使用するクラスを受け入れることができます。

このタイプのコーディングは、ほとんどのOOP設計パターンで使用され、後でコードを非常に簡単に変更できます。これらは、AGILEプログラミングの基礎の一部です。


1
またはBのサブクラス
メズ

7

@pjskepticには良い答えがあり、@ KamilTomšíkにはその答えに対する良いコメントがあります。

PHPのような動的に型付けされた言語の素晴らしい点は、オブジェクトでメソッドを使用しようとすることができ、メソッドが存在しない限り叫びません。

PHPのような動的に型付けされた言語の問題は、オブジェクトでメソッドを使用しようとすることができ、メソッドが存在しないときに悲鳴を上げることです。

インターフェイスは、未知のオブジェクトのメソッドを呼び出す便利な方法を追加し、メソッドがそこにあることを確実にします(必ずしも正しいか、機能するわけではありません)。これは言語の必須部分ではありませんが、コーディングをより便利にします。これにより、強く型付けされたOOP開発者は強く型付けされたPHPコードを記述でき、別のPHP開発者によって記述された緩く型付けされたPHPコードと一緒に動作できます。

次のような関数:

foo( IBar $bar )
{
  $baz = $bar->baz();
  ...
}

より便利です:

foo( $bar )
{
  if ( method_exists( $bar, 'baz' ) )
  {
    $baz = $bar->baz();
  }
  else
  {
    throw new Exception('OMGWTF NO BAZ IN BAR!');
  }
  ...
}

そして、私見のシンプルで読みやすいコードは、より良いコードです。


1
代わりに行うことは、メソッドをチェックせず、誰かが間違ったデータを使用して関数を呼び出したときにクラッシュして書き込みを行うだけです。誰かがあなたの関数を間違って使用する場合、それはあなたの問題ではありません。
レイノス

いいえ、正確に-あなたの例では、任意の動的な「鴨」を渡したいだれでも、プロキシのように、アダプタ、デコレータなどにとっては悪夢である
カミルTomšík

1
@カミル?どうして。プロキシは、この関数で使用できるようにするためのインターフェイスを実装していないもののラッパークラスになります。
タイラーマック

__call()を使用する@tylermacダイナミックプロキシ-__callが唯一のメソッドである場合、IBarを実装できないため、foo(IBar $ bar)に渡すことができません
KamilTomšík11年

5

あなたがダックタイピングをしているなら、それらは完全に役に立たない、実際にダックタイピングをするとき、それはタイプヒンティングを使用するライブラリ/フレームワークで作業するのはかなり面倒です。

これは、あらゆる種類の動的なメタプログラミング(魔法のメソッド)にも当てはまります。


3

PHPは緩くも強くもありませんが、動的に型付けされます。

インターフェイスについて、最初に自問すべきことは次のとおりです。インターフェイスの利点のほとんどは何ですか?

OOPでは、インターフェイスは型だけでなく、動作についても同様です。

PHPには型ヒント機能もあるため、Javaなどの純粋なoo言語の場合と同じようにインターフェイスを使用できます。

interface File
{
    public function getLines();
}

CSVFile implements File
{
    public function getLines()
    {}
}

XMLFile implements File 
{
    public function getLines()
    {}
}

JSONFile implements File 
{
    public function getLines()
    {}
}

class FileReader
{
    public function read(File $file)
    {
        foreach($file->getLines() as $line)
        {
            // do something
        }
    }
}

PHPインターフェースの実装では、PHPUnitを使用して抽象クラスのモックを作成することもできます。これは機能の地獄です:

public function testSomething()
{
    $mock = $this->getMockForAbstractClass('File');

    $mock->expects($this->once())
         ->method('getLines')
         ->will($this->returnValue(array()));

    // do your assertions
}

したがって、基本的に、言語機能を使用してPHPでSOLID互換アプリケーションを作成できます。そのうちの1つはインターフェイスです。


0

依存関係の注入には、具体的なものよりもインターフェースがはるかに役立ちます。最低限の例として:

interface Istore { 
  public function save(); 
}

class Article_DB implements Istore 
{ 
  public function save($data) 
  {
    // do save to format needed.
  } 
}

class Article
{
   private $content;

   public function content($content)
   {
     $this->content = $content;
   }

   public function save(Istore $store)
   {
     $store->save($this->content);
   }
}

$article = new Article();
$article->content('Some content');

$store = new Article_DB();
$article->save($store);

ニーズが変わって、pdfに保存する場合は、次のように言います。Articleクラスを汚染する代わりに、その目的のために新しいクラスを作成できます。

class Article_PDF implements Istore 
{ 
  public function save($data) 
  {
    // do save to format needed.
  } 
}


$article = new Article();
$article->content('Some content');

$store = new Article_PDF();
$article->save($store);

Articleクラスには、保存に使用するクラスがIstoreインターフェイスを実装する必要があるというコントラクトがあります。どこに保存するか、どのように保存するかは気にしません。


-1

インターフェイスを実装する「偽の」実際のオブジェクトを提供できます。その後、実サーバー、ファイルシステム、ソケット、データベースなどを必要とせずにコードの一部を単体テストできます。


-3

多くの人がこの方法で答えるのを嫌うかもしれませんが、入力の問題の解決策はPHPで簡単に修正できます。はいタイプがデフォルトで想定しているので、PHPは緩くれ、入力されることができます、特にほとんどの人が問題とする比較演算において、いくつかの問題引き起こす性あり。そうは言っても、使用しているものを必要な型にキャストし、ビットごとの比較演算子を使用すると、PHPは厳密に型指定された言語と同じくらい厳密になります。私が言っていることについて考えることができる最も簡単な例は次のとおりです。

$ myVar =(int)0; $ myOtherVar = '0';

比較($ myVar == $ myVar)は等しい(bool)true

しかし、($ myVar === $ myVar)を比較すると、「型指定された」比較のようにfalse(bool)になります

PHPの動作に問題がある場合、Javaでプログラムを実行してライブにするか、それが目的どおりに機能するように使用するか、開発者がこれらのことについて議論するのを止めてほしいと思います。とにかく、それについての愚痴はあなたにとって何をしますか?一日中めちゃくちゃに言い訳をする?他の人よりも見栄えを良くしますか?自分自身について非常に強く感じているので、他の誰かを悪く見せたいと思っているのは素晴らしいことですが、実際にはあなたの好みであり、誰にでもあなたの信念を強要することは、彼らが3つのことを引き起こすことに慣れていない方法でコードを作るだけです:

1)彼らはあなたの方法でコーディングしますが、あなたの標準では「面倒」です(Javaプログラマーが最初のPHPプログラムを作成するのを見たことがありますか?その逆も同様です。

2)泣き言を言う他の何かを見つける

3)彼らが生産するのにおそらく時間がかかるでしょう。また、短期的には見た目が良くなるかもしれませんが、チーム全体としては悪く見えます(コードが他の誰かよりも遅くなる可能性があり、チームが妥当な時間枠で成果物を満たしている限り、それは必ずしも悪いことではありません、しかし、通常少し速く走っている人に習慣を強要すると、チーム全体が遅くなり、非常に厳しいワークフローで悪化する可能性があります)

私は個人的に手続き型のPHPコードを書くことを好みますが、いくつかの異なる言語でOOPを使用して完全なプログラムを書くことができます。そうは言っても、良いOOPコードと悪いOOPコード、そして良い手順コードと悪い手順コードを見てきました...それは実際には練習とは関係ありませんが、あなたが使用する習慣と、多くのことが私の解釈された感情です...それは、それらの開発者について悪い話をしたり、「私のやり方は最高です」と自慢することを意味するわけではありませんBS、それは私にぴったりです私の仕事に満足しており、それを誇りに思っています。標準を確立する必要がある理由はありますが、選択した標準に含めることは非常に重要です...それを胸から出してくれてありがとう。すてきな一日を。


-4
  1. インターフェイスはOOPパラダイムの一部です。そのため、オブジェクト指向のパーツやシステムを作成しようとすると、多くの場合に非常に役立ちます。
  2. そう。何故なの?;-)

例:データをキャッシュする必要があります。どうやって?キャッシングにはさまざまなエンジンがありますが、どれが最適ですか?key、get、put、clearなどの一連のメソッドを持つICacheDriverインターフェイスを持つ抽象レイヤーがある場合、誰が気にします。現在のプロジェクトで必要なものを実装し、別のプロジェクトが必要なときに変更します。または、toStringの単純な使用法。さまざまな表示可能なオブジェクトのセットがあります。Stringableインターフェイスを実装し(toStringメソッドについて説明します[PHPには実際にはそのようなインターフェイスはありませんが、たとえば)]、すべてのオブジェクトを(string)$ objで相互作用します。switch(true){case $ obj isntanceof A1: "do 1";の代わりに必要なことはすべてあります。ブレーク; ...}

シンプル。だから「なぜ?」という質問はありません。「それをもっとうまく使う方法」があります。;-) がんばろう。


-5

私の推測。

PHPは多くの初心者レベルのプログラマーによって使用されており、初心者レベルのプログラマーは大学でjava教えられています。

プログラミング101コースの後、彼らはZendのしつこい作業を始めます。Java機能が欲しいのは、それが彼らが考えるように教えられた方法だからです。

Zendは実用的です。機能を追加する方が、ずっと先にふりをするよりも簡単です。
これにより、ユーザーを退場させる代わりに、より多くのユーザーを獲得できるため、良い結果になります。

このプロセスの別のインスタンス?.NETやJavaのコースを卒業したばかりの人も、Foundation ClassesのFrameworksを望んでいます。ZendがZend Frameworkを芽生えさせるまで、彼らはそれを口にしません。これにより、さらに多くのユーザーが購入します。そしてさらに...

(PHPチームがいることが知られている唯一の言語機能戦っ年間では、ありますgoto


私のビジョンでPHP12は、おそらく機能とデータ型のパラダイムへのウィンクを備えた世界のすべての構文機能を備えています(perlを殺したので、抽象化レイヤーランタイムを取得しないことを願っています)goto
ZJR

「あなたが20歳のとき、それは難しいです」どのように年齢がおそらくこれらの概念のいずれかを理解することに関係があるのでしょうか?
エヴィカトス

@Evicatosの高校生の並べ替えプログラムですが、彼らは通常、悪い教師、貧弱な命名規則を持ち、維持できない塊を生成します。彼らは大学を始める間、すぐにプログラムすることを学びます。それを実現するには数年かかります。その後、彼らは、最初の数年間に教えられてきた、ハードタイプの、業界に恵まれた、学問的に称賛された言語から分岐し始め、より実用的でアヒル型の言語に変わります。これは多くのプログラマーが共有する武士道だと思います。繰り返しますが、これはあなたの経験を反映していないかもしれません。あなたは独学の賢人かもしれません。もしそうなら、方法を教えてください。
ZJR
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.