88

なぜ PHP Trait (PHP 5.4) がインターフェイスを実装できないのか疑問に思っています。

user1460043 の回答からの更新 => ...特定のインターフェイスを実装するためにそれを使用するクラスを要求することはできません

a が を実装Class Aしている a を使用している場合、 が を間接的に実装する必要があると人々が考える可能性があるためです (これは、トレイト メソッドの名前を変更できるため、正しくありません)。Trait Tinterface IClass Ainterface IClass A

私の場合、私の特性は、特性を使用するクラスが実装するインターフェースからメソッドを呼び出しています。

トレイトは、実際にはインターフェースのいくつかのメソッドの実装です。したがって、私の特性を使用するすべてのクラスがインターフェイスを実装する必要があるコードを「設計」したいと考えています。これにより、Trait はインターフェイスによって定義されたクラス メソッドを使用し、それらがクラス内に存在することを確認できます。

4

4 に答える 4

108

あなたができないので、本当に短いバージョンはより簡単です。それはTraitsの仕組みではありません。

PHP で記述use SomeTrait;する場合、(効果的に) コンパイラに、コードを Trait からコピーして、それが使用されているクラスに貼り付けるように指示します。

はクラス内にあるため、クラスuse SomeTrait;に追加implements SomeInterfaceすることはできません。クラスの外にある必要があるためです。

"PHP に Traits 型がないのはなぜですか?"

インスタンス化できないからです。コードで参照できるオブジェクトや型とは対照的に、特性は実際には単なる言語構造です(特性コードをコピーしてこのクラスに貼り付けるようコンパイラーに指示します)。

したがって、私の特性を使用するすべてのクラスがインターフェイスを実装する必要があるコードを「設計」したいと考えています。

これは、抽象クラスをuseトレイトに使用して強制し、そこからクラスを拡張することができます。

interface SomeInterface{
    public function someInterfaceFunction();
}

trait SomeTrait {
    function sayHello(){
        echo "Hello my secret is ".static::$secret;
    }
}

abstract class AbstractClass implements SomeInterface{
    use SomeTrait;
}

class TestClass extends AbstractClass {
    static public  $secret = 12345;

    //function someInterfaceFunction(){
        //Trying to instantiate this class without this function uncommented will throw an error
        //Fatal error: Class TestClass contains 1 abstract method and must therefore be 
        //declared abstract or implement the remaining methods (SomeInterface::doSomething)
    //}
}

$test = new TestClass();

$test->sayHello();

ただし、特性を使用するクラスに特定のメソッドがあることを強制する必要がある場合は、そもそも抽象クラスであるべき場所で特性を使用している可能性があると思います。

または、ロジックが間違っていること。インターフェースを実装するクラスに特定の機能があることを要求することを意図しています。特定の機能がある場合、インターフェースを実装していると宣言する必要があるわけではありません。

編集

実際、Traits 内で抽象関数を定義して、クラスにメソッドの実装を強制することができます。例えば

trait LoggerTrait {

    public function debug($message, array $context = array()) {
        $this->log('debug', $message, $context);
    }

    abstract public function log($level, $message, array $context = array());
}

ただし、これでもトレイトにインターフェイスを実装することはできず、クラスが満たす必要があるコントラクトを定義する際にインターフェイスがトレイトよりもはるかに優れているため、依然として悪い設計のような匂いがします。

于 2013-02-14T01:13:57.753 に答える
10

[...]私の特性を使用したいすべてのクラスがインターフェースを実装しなければならないコードを「設計」します。これにより、Trait はインターフェイスによって定義されたクラス メソッドを使用し、それらがクラス内に存在することを確認できます。

これは非常に理にかなっているように聞こえますが、設計に何か問題があるとは言えません。トレイトはこの考えを念頭に置いて提案されています。ここで 2 番目のポイントを参照してください。

  • トレイトは、動作を実装する一連のメソッドを提供します。
  • トレイトには、提供された動作のパラメーターとして機能する一連のメソッドが必要です。
  • [...]

Schärli et al, Traits: Composable Units of Behaviour, ECOOP'2003, LNCS 2743, pp. 248–274, Springer Verlag, 2003, Page 2

したがって、インターフェイスを「実装」するのではなく、インターフェイスを必要とするトレイトが必要であると言う方が適切かもしれません。

PHP でこの「特性には (実装する消費者クラスに) インターフェースが必要」という機能を持たせることが不可能な理由はわかりませんが、現在は欠けているようです。

@Danack が彼の回答で指摘しているように、特性で抽象関数を使用して、特性を使用するクラスからそれらを「要求」できます。残念ながら、プライベート関数でこれを行うことはできません。

于 2016-08-11T13:16:40.017 に答える