web-dev-qa-db-ja.com

PHPで抽象クラスを使用する場合の利点は何ですか?

可能性のある複製:
インターフェースvs抽象クラス

PHPで抽象クラスを使用する場合の利点は何ですか?

抽象クラスまたはインターフェイスを使用する場合の目的は何ですか?

両方とも本文なしで定義名を作成しています

28
Sreeraj

PHPで抽象クラスを使用する場合の利点は何ですか?その上で何か良いものを見つけることができません。抽象クラスを使用せずにすべての作業を簡単に行うことができると思いますか?

もちろんできます。ただし、ほとんど同じタイプのオブジェクトが多数ある場合は、共通の機能を「基本」クラスに抽出すると役立つ場合があります。つまり、そのロジックを複製する必要はありません。

ただし、実際には2つの理由があります。私にとっての最初の理由は、抽象クラスのすべての子孫が同じ型を持ち、どちらもまったく同じインターフェースに準拠していることです。つまり、たとえばPDFドキュメントはdocxドキュメントと同じインターフェイスを持ち、クライアントコードは処理するオブジェクトを気にする必要がありません。短い例(PHPの場合)です。

<?php
abstract class Document {
    protected $author;

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

    abstract public function render( );

    public function author( ) {
        return $this->author;
    }
}

class PdfDocument extends Document {
    public function render( ) {
        // do something PDF specific here.
    }
}

class DocxDocument extends Document {
    public function render( ) {
        // do something DOCX specific here.
    }
}


class DocumentHandler {
    public function handle( Document $document ) {
        $this->log( 'Author has been read ' . $document->author( ) );
        return $document->render( );
    }
}

まず第一に; DocumentHandlerクラスは、実際に処理しているドキュメントのタイプを認識していないことに注意してください。それも気にしません。それは無知です。ただし、doesは、2つのタイプのドキュメント間のインターフェースが同じであるため、どのメソッドを呼び出すことができるかを認識しています。これはpolymorphismと呼ばれ、Documentインターフェースの実装で簡単に実現できます。

2番目の部分は、すべてのドキュメントに作成者がいて、その作成者が常に要求されている場合、メソッドをPdfDocumentとDocxDocumentにコピーできますが、自分で複製することになります。たとえば、著者に大文字を使用させたい場合、return $ this-> authorをucwords($ this-> author)に変更する場合は、何回でも行う必要があります。そのメソッドをコピーしました。抽象クラスを使用すると、クラス自体を不完全としてマークしながら、動作を定義できます。これは非常に便利です。

お役に立てば幸いです。

68
Berry Langerak

抽象クラスは、同じメソッドを持つクラスが多数ある場合に役立ちます。

例:

_abstract class Foo {
  public function foo1() {
    //Do something
  }

  public abstract class foo2();
}

class Bar extends Foo {
  public class foo2() {
    //Do something
  }
}

class Baz extends Foo {
}
_

何が起こるか:

  • new Foo();は使用できません。Fooは抽象です。
  • Bar.foo1()Baz.foo1()を使用できるようになり、同じように動作します。
  • Bazはabstactメソッド_foo2_を実装していないため、エラーが発生します。

それが役に立つ例:

_abstract class Shape {
  public function display() { /* ... */ }
  //...
}

class Circle extends Shape {
  //...
}

class Rectangle extends Shape {
  //...
}

//...
_

すべてのクラスがdisplay()を使用できるようにしたいのですが、それだけでは「シェイプ」などはありません。

10
SteeveDroz

抽象クラスのすべてのメソッドが空である必要はありません。処理するいくつかの基本的なメソッド(およびプロパティ)がある場合があります。たとえば、eショップがあり、製品をインポートするための抽象クラスを開発しているとします。このクラスには、製品をdbに保存するメソッド、製品のURLを生成するメソッド、およびどこかから製品を取得する抽象メソッドがあります(したがって、拡張クラスに実装する必要があります)。インターフェースには空のメソッドのみがあり、プロパティはありません(ただし、定数を持つことができます)。そのため、実際のロジックはなく、メソッド定数、メソッド名、およびそれらのアクセス修飾子のみである場合があります。

2
cypher

名前が示すように、インターフェイスの目的は、クラスとインスタンスによって提供されるデータとメソッドへのインターフェイスを明示的に宣言することです。これらのメソッドをすぐにコーディングする必要はありません。典型的な例は、幾何学的形状の例です。このようなインターフェースは、そのような形状の領域を生成するメソッドを定義できます。

_interface Shape {
    public function getArea();
}
_

CircleSquareのように、このインターフェースを実装するさまざまなクラスがいくつかあり、メソッドgetArea()に異なる実装を提供します。次に、幾何学的形状に関する情報を表示する関数を実装できます。

_function displayInformation(Shape $shape) {
    echo "The area of this shape is: " . $shape->getArea();
}
_

Shapeインターフェースを実装したオブジェクトをこの関数に渡すことができ、インターフェースはgetArea()メソッドが存在することを保証します。

もちろん、これらの概念は、PHPよりも強く型付けされたプログラミング言語でより役立つ可能性があります。

1
cg.