DOMDocument を拡張し、独自の Document 拡張機能を作成して、DOMNode を拡張するにはどうすればよいですか?
PHP では、多重継承はありません。つまり、あなたがやろうとしていることは PHP では不可能です。その理由は、DOMDocument が DOMNode (DOMElement、DOMAttr、DOMText などと同様) から拡張されているため、この継承パスは既に終了しているためです ( DaveRandom はこれをより長く説明し、おそらく彼の答えでより適切に表現しました。
PHP 5.4 では、すべてのサブタイプ間で共有されるコード (たとえば、 DOMNodeに入れるコード) をtraitsに入れることができるため、状況が少し改善されました。
作成した各サブタイプは、これらの特性を使用できます(すぐに例を示します)。
さらにそれらをすべてDOMNode型にしたい場合は、空のインターフェースを定義して、すべてのサブタイプで実装することもできます。
以下は、模範的なスクレイパー ライブラリからのその手法の例です。
class ScraperDoc extends DOMDocument implements ScraperNodeType
{
use ScraperNodeTrait;
...
示されているように、インターフェイス ( ScraperNodeType
) とトレイト ( ScraperNodeTrait
) も実装しています。
したがって、インターフェースがあります:
/**
* Empty Interface for typing reasons (instanceof operator and traits
* work not well, this interface cures that limitation a bit)
*/
interface ScraperNodeType
{
}
そして、特徴があります。トレイトを初めて使用する場合は、コードの例を次に示します。これは、トレイトを実装するすべてのノードに文字列コンテキストを提供する 1 つのメソッドのトレイトです (アイデアを示すために、元のライブラリから短縮されています)。
Trait ScraperNodeTrait
{
public function __toString()
{
/* @var $this DOMNode */
return trim($this->textContent);
}
}
これは、Ruby の traits/mixins ほど流動的ではありませんが、PHP で (これまでのところ非動的コードで) 可能な限り流動的です。
これはまだ、独自の階層を作成する際のすべての問題を解決するわけではありませんが、この手法 (特性 + 空のインターフェイス) について知っておく必要があると思います。
これは継承図で、DOMNode
上に 、次に PHP DOM 拡張から拡張された型、次にこれらのユーザーランド拡張と、トレイト (左下) およびインターフェース (右下) との関係を示しています。
右側のクラスターは、この回答の一部ではないイテレーターと simplexml に関連しているため、直接の関心事ではありません。DOMNodeList
たとえば、PHPでオーバーロードできないことを示していますが。SimpleXML で可能な非常識な動きがいくつかあります。これが、そのライブラリが全体像の一部としてそれを持っている理由です。
次に、左下に、これまでで最高の PHP URL クラスである Net_URL2 への参照があります。ライブラリはそれから拡張され、独自の URL タイプを持ち、外部ライブラリは少なくともコードベースに階層化されます。
DOMDocument 継承図に基づくスクレイピング ライブラリの例 (フルサイズ)
これが役に立ち、インスピレーションを与えてくれることを願っています。前回、DOMDocument の拡張に関する質問に答えたのは、DOMDocument はモデルですが、あなたのモデルではないという現象に関するものでした: