LoginSignup
0
0

More than 3 years have passed since last update.

[PHP]具象メソッドを持つインターフェースのようなものをtraitで実現する

Last updated at Posted at 2020-05-05

概要

今日はめずらしく真面目なプログラミングの記事です。
interface についての説明はこちらをどうぞ。

PHP: オブジェクト インターフェイス - Manual

interface とは本来抽象メソッドしか持つことができません。しかし、とある具象メソッド内で使用されるパラメータの実装を強制したい場合どうすればよいか、わたしなりに考えてみましたので今日はそんな話をしたいとおもいます。

状況

まずは下記のサンプルをご覧ください。

共通メソッドを持つクラス
class Common
{
    public function hoge()
    {
        return 'called common method';
    }
}
共通メソッドを使うクラス(1)
use Common;
class A
{
    public function foo()
    {
        $common = new Common();
        $common->hoge();
    }
}
共通メソッドを使うクラス(2)
use Common;
class B
{
    public function bar()
    {
        $common = new Common();
        $common->hoge();
    }
}

まあ特に変わったところのないクラスです。
このとき、Common クラスの hoge() メソッド の内部で使用するパラメータを動的に変更したい という場合はどうするのが良いでしょうか。

手取り早いのは引数を追加して外から渡す方法でしょう。
メソッドの引数でもいいですし、コンストラクタの引数でもいいとおもいます。

引数を持たせたよ
class Common
{
    public function hoge(string $str)
    {
        return "{$str}: called common method";
    }
}

これでも解決するのですが、

  • 引数を準備する際に単純な値のリテラルではすまない
  • パラメータの引数が多くなる

といった場合にちょっと困ってきます。
このとき、interface で必要なパラメータの準備を強制させることができれば、新しいクラスへの導入をよりスムーズに行えるメリットもあるのでできればそのようにしたいのですが、interface だと抽象メソッドしか書けないのでどうしたものかというところです。

というわけで本題

trait を組み合わせることで、限りなく近いものを実現できると考えました。
具体的にはこのようなイメージです。

  • trait → 具象メソッド
  • interface → 抽象メソッド

サンプル

先ほどの例を書き換えてみます。

まず共通処理を trait にします

このとき、抽象メソッドを trait 内に組み込んでしまう のがポイントです。

Commonをtraitにします
trait Common
{
    public function hoge()
    {
        $param = $this->getParam();
        return "{$param}:called common method";
    }
}

実装を強制したい部分をinterfaceにします

interface Params
{
    /**
     * @return string
     */
    public function getParam(): string;
}

使用クラスに導入します

作った trait と interface を、導入したいクラスに適用させます

class A implements Params
{
    use Common;
    public function foo()
    {
        $this->hoge();
    }

    public function getParam(): string
    {
        return 'class A param';
    }
}

まとめ

このように、trait と interface をセットで使えば、「この trait と interface を読み込んで、あとは抽象メソッドを実装すれば、メソッド****がお好きなクラスで使えますよ」みたいなことが可能です。

もっとスマートな方法があるのかもしれませんが、事例のひとつとしてよかったら参考にしてみてください。


※追記
スマートな方法をコメントで教えていただけました。
@nishimura さんありがとうございました!

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0