web-dev-qa-db-ja.com

PHPトレイトを使用して多重継承をシミュレートする

この質問について、私は私の現在のデザインと特性を使用するという私の考えを提示したいと思います。特性の私の理解が正しいかどうか、そして私の問題はそれらを含まない別の設計で解決できるかどうかを知りたいです。

フレームワークの現在のクラス階層は次のようになります。

interface IPage { /* ... */ }
interface IForm extends IPage { /* ... */ }
abstract class AbstractPage implements IPage { /* ... */ }
abstract class AbstractForm extends AbstractPage implements IForm { /* ... */ }

私が使用していたフレームワークに基づくアプリケーションでは、次のものがありました。

abstract class AbstractBasePage extends AbstractPage { /* ... */ }

したがって、この特定のアプリケーションのすべてのページに、フレームワークや他のアプリケーションに共通していないものをさらに追加することができます。最初のスニペットに示されているように、ページとフォームへの分離を実装するまで、これはうまくいきました。今私はこのようなもので終わった:

abstract class AbstractBasePage extends AbstractPage { /* ... */ }
abstract class AbstractBaseForm extends AbstractForm { /* ... */ }

1つのアプリケーションに、ページに特別なものがテンプレートに表示されるかどうかを示す変数が各ページとフォームにあると仮定します。 AbstractBasePageAbstractBaseFormに同じ変数を導入する必要があります。これを行うと、両方のスニペットの同期を維持する必要があり、これはまったく良くありません。

私は、変数と関数を両方のクラスに公開するトレイトを作成することを考えていました。これらのクラスは、対応する関数で参照できます。このような特性を使用すると、少なくとも両方のクラスから呼び出される公的にアクセス可能なメソッドを1つ導入できるが、それ以外にまともな抽象化があるため、コードの重複を減らすことができるでしょう。

これはどんな特性が役立つと思われていますか?より適切なアプローチはありますか、この場合の特徴は実際に推奨されるデザインですか?

3

この特定のケースでは、IPageによって拡張されるコントラクトとしてインターフェイス(フレームワークで使用される関数を含む)を導入することになりました。さらに、トレイトのページとフォームが同じである特定の実装があり、それがフレームワーククラスAbstractPageAbstractFormで使用されました。

上記の実装はフレームワーク自体の内部にあり、簡潔な設計になっています。これは、私のアプリケーションでも同様に使用されます。アプリケーションでは、両方のページとフォームで同じ変数と関数を保持するトレイトを導入しました。これは、AbstractBasePageおよびAbstractBaseFormクラスで使用されます。

このシナリオでは、継承を使用して簡単に実行できるものではなく、さまざまなクラス階層の一部であるクラスに導入できるものを追加したかったので、本質的に言語支援のコピーアンドペースト機能が必要でした。したがって、私は特性を使用することにしました。

0

具体的な提案をするのに十分な詳細はありませんが、クラス階層は [〜#〜] isp [〜#〜] に反すると思います。巨大な抽象クラスも必要だとは思いません。

[〜#〜] srp [〜#〜] に従って、それぞれの目的に特化したインターフェースを作成することを検討してください。そして、トレイトを使用してビヘイビアーをクラスに入れるか(プロジェクトについて詳しく知っていない限り推奨されません)、継承よりも構成を優先して同じようにします。

構図はいろいろな使い方ができると思います。しかし、私の頭に浮かぶのは、特定のタスク用に2つのインターフェースのセットを作成することです。 1つは単一のメソッドを持つ包含クラス用で、もう1つはクラス用で、その動作を実装しています。

  interface ISpecificActionProvider {
    /**
      * @return ISpecificActionHandler
      */
    public function getSpecificActionHandler();
  }

このアドバイスは、プロジェクトのニーズに応じて、良い場合もあれば悪い場合もあります。これは、アイデアのみを提供するために提供されています。

0