質問

PHP5 がまだ多重継承をサポートしていないという事実を回避する、適切でクリーンな方法を探しています。クラス階層は次のとおりです。

メッセージ
- メール
-------- 招待状テキストメッセージ
-- 電子メールメッセージ
-------- 招待メールメッセージ

2 種類の Invitation* クラスには多くの共通点があります。両方が継承する共通の親クラス、Invitation が欲しいと思っています。残念ながら、彼らは現在の先祖と多くの共通点もあります...テキストメッセージと電子メールメッセージ。ここでは多重継承が古典的に望まれます。

問題を解決するための最も軽量なアプローチは何ですか?

ありがとう!

役に立ちましたか?

解決

アレックス、多重継承が必要になる場合は、オブジェクトの構造が多少間違っていることを示していることがほとんどです。あなたが概説した状況では、あなたにはあまりにも広範な階級責任があることがわかります。Message がアプリケーション ビジネス モデルの一部である場合、出力のレンダリングについては考慮すべきではありません。代わりに、責任を分割し、テキストまたは HTML バックエンドを使用して渡されたメッセージを送信する MessageDispatcher を使用することもできます。コードはわかりませんが、次のようにシミュレートしてみましょう。

$m = new Message();
$m->type = 'text/html';
$m->from = 'John Doe <jdoe@yahoo.com>';
$m->to = 'Random Hacker <rh@gmail.com>';
$m->subject = 'Invitation email';
$m->importBody('invitation.html');

$d = new MessageDispatcher();
$d->dispatch($m);

このようにして、Message クラスに特殊化を追加できます。

$htmlIM = new InvitationHTMLMessage(); // html type, subject and body configuration in constructor
$textIM = new InvitationTextMessage(); // text type, subject and body configuration in constructor

$d = new MessageDispatcher();
$d->dispatch($htmlIM);
$d->dispatch($textIM);

MessageDispatcher は、HTML として送信するかプレーン テキストとして送信するかを決定することに注意してください。 type Message オブジェクトのプロパティが渡されました。

// in MessageDispatcher class
public function dispatch(Message $m) {
    if ($m->type == 'text/plain') {
        $this->sendAsText($m);
    } elseif ($m->type == 'text/html') {
        $this->sendAsHTML($m);
    } else {
        throw new Exception("MIME type {$m->type} not supported");
    }
}

要約すると、責任は 2 つのクラスに分割されます。メッセージの設定は InvitationHTMLMessage/InvitationTextMessage クラスで行われ、送信アルゴリズムはディスパッチャに委任されます。これは戦略パターンと呼ばれます。詳細についてはこちらをご覧ください。 ここ.

他のヒント

「is-a」関係を「has-a」関係に置き換えることができるでしょうか?招待状にはメッセージが含まれる場合がありますが、必ずしもメッセージである必要はありません。招待状が確認される可能性があり、メッセージモデルとの相性が良くありません。

「組成 vs.」で検索します。それについて詳しく知りたい場合は、「継承」を参照してください。

フィルの言葉を引用させていただくなら このスレッド...

PHP は Java と同様、多重継承をサポートしていません。

PHP 5.4 では次のようになります。 特徴 この問題の解決策を提供しようとします。

それまでの間、クラスの設計を再考することをお勧めします。クラスにAPIを拡張した後に複数のインターフェイスを実装できます。

そしてクリスは……

PHPは実際には複数の継承をサポートしていませんが、それを実装する(やや面倒な)方法がいくつかあります。いくつかの例については、このURLをご覧ください。

http://www.jasny.net/articles/how-i-php-multiple-inheritance/

どちらも有益なリンクを持っていると思いました。特性やミックスインを試すのが待ちきれません...

Symfony フレームワークには、 このためのミックスインプラグイン, 使用しない場合でも、アイデアだけでもチェックしてみるとよいでしょう。

「デザイン パターン」の答えは、共有機能を別のコンポーネントに抽象化し、実行時に構成することです。招待機能を、継承以外の何らかの方法で Message クラスに関連付けられるクラスとして抽象化する方法を考えてください。

これを解決する方法として、PHP 5.4 のトレイトを使用しています。http://php.net/manual/en/ language.oop5.traits.php

これにより、extends を使用した古典的な継承が可能になりますが、共通の機能とプロパティを「トレイト」に配置することも可能になります。マニュアルには次のように書かれています。

Traits は、PHP などの単一継承言語でコードを再利用するためのメカニズムです。特性は、開発者が異なるクラス階層に存在する複数の独立したクラスでメソッドのセットを自由に再利用できるようにすることで、単一継承の制限の一部を軽減することを目的としています。

まるで デコレータパターン 適切かもしれませんが、詳細がなければ判断するのは困難です。

これは質問でもあり、解決策でもあります...

魔法の_はどうですか?電話()、_get()、__set() メソッド?このソリューションはまだテストしていませんが、multiInherit クラスを作成したらどうなるでしょうか。子クラスの保護された変数には、継承するクラスの配列を含めることができます。マルチインターフェイス クラスのコンストラクターは、継承される各クラスのインスタンスを作成し、それらをプライベート プロパティ (_ext など) にリンクできます。__call() メソッドは、_ext 配列内の各クラスでメソッド_exists() 関数を使用して、呼び出す正しいメソッドを見つけることができます。__get() と __set を使用して内部プロパティを見つけることも、参照の専門家であれば、子クラスと継承されたクラスのプロパティを同じデータへの参照にすることもできます。オブジェクトの多重継承は、それらのオブジェクトを使用するコードに対して透過的になります。また、_ext 配列がクラス名でインデックス付けされている限り、内部オブジェクトは必要に応じて継承されたオブジェクトに直接アクセスできます。私はこのスーパークラスを作成することを構想していましたが、それが機能すると、さまざまな悪いプログラミング習慣が身につく可能性があると感じているため、まだ実装していません。

あなたが何をしているのかを明確にするためにいくつか質問があります:

1) あなたのメッセージはオブジェクトですか ただ メッセージが含まれています。例:本文、受信者、予定時刻?2) Invitation オブジェクトをどうするつもりですか?EmailMessage と比較して特別に扱う必要がありますか?3) もしそうなら、それの何が特別ですか?4) そうであれば、なぜ招待に対してメッセージ タイプを異なる処理する必要があるのでしょうか?5) ウェルカム メッセージまたは OK メッセージを送信したい場合はどうすればよいですか?それらも新しいオブジェクトですか?

メッセージの内容を保持することのみを考慮すべきオブジェクトのセットに、メッセージの処理方法ではなく、あまりにも多くの機能を組み合わせようとしているように思えます。私にとって、招待状と標準的なメッセージに違いはありません。招待に特別な処理が必要な場合、それはメッセージ タイプではなくアプリケーション ロジックを意味します。

例えば:私が構築したシステムには、SMS、電子メール、その他のメッセージ タイプに拡張された共有ベース メッセージ オブジェクトがありました。しかし:これらはさらに拡張されませんでした。招待メッセージは、電子メール タイプのメッセージを介して送信される単純な事前定義されたテキストでした。特定の招待アプリケーションは、招待の検証およびその他の要件に関係します。結局のところ、あなたがやりたいのは、メッセージ X を受信者 Y に送信することだけであり、受信者 Y はそれ自体が独立したシステムであるはずです。

Javaと同じ問題。その問題を解決するには、抽象関数を備えたインターフェイスを使用してみてください

PHP はインターフェイスをサポートしています。ユースケースによっては、これが良い選択肢になる可能性があります。

Message クラスのすぐ下に Invitation クラスがあるのはどうでしょうか?

したがって、階層は次のようになります。

メッセージ
- - 招待
- - - メール
------ メールメッセージ

そして、Invitation クラスに、InvitationTextMessage と InvitationEmailMessage にあった機能を追加します。

招待状は実際にはメッセージの一種ではなく、メッセージの機能であることはわかっています。したがって、これが良い OO デザインであるかどうかはわかりません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top