17

1 つのクラスで機能を数回再利用したいと考えています。この機能は、プライベート変数に依存しています。

trait Address {
    private $address;

    public function getAddress() {
        return $this->address;
    }

    public function setAddress($address) {
        $this->address = $address;
    }
}

特性を 2 回使用することがわかった唯一の方法は次のとおりです。

class User  {
    use Address {
        getAddress as getHomeAddress;
        setAddress as setHomeAddress;

        getAddress as getWorkAddress;            
        setAddress as setWorkAddress;
    }
}

問題は、これを行うことにより、プライベート変数$addressがさまざまなメソッド間で共有され、コードが期待どおりに機能しないことです。

$user = new User();
$user->setHomeAddress('21 Jump Street');
echo $user->getWorkAddress(); // 21 Jump Street

プライベート変数を共有せずに、実際に特性を 2 回使用する解決策はありますか?

4

4 に答える 4

21

で特性を宣言してもuse、その特性のインスタンスは作成されません。特性は基本的に、使用するクラスにコピー アンド ペーストされる単なるコードです。はそのasメソッドのエイリアスのみを作成します。たとえば、次のようなものを追加します

public function getHomeAddress()
{
    return $this->getAddress();
}

あなたの User クラスに。しかし、それはまだその1つの特性にすぎません。2 つの異なる$addressプロパティはなく、1 つだけです。

__callメソッドをプライベートにしてから、メソッド名をスイッチ/ケース化し、アドレスに配列を使用することにより、メソッドへのパブリック呼び出しを委任できます。

trait Address {
    private $address = array();

    private function getAddress($type) {
        return $this->address[$type];
    }

    private function setAddress($type, $address) {
        $this->address[$type] = $address;
    }

    public function __call($method, $args) {
        switch ($method) {
            case 'setHomeAddress':
                return $this->setAddress('home', $args[0]);
            // more cases …
        }
    }
}

しかし、それは単なるワームの缶詰です。

言い換えれば、特性を使ってやろうとしていることを正気で行うことはできません。2 つの異なる特性を使用します。または、古き良き集約を使用して、具体的なプロキシ メソッドを追加します。

于 2012-11-27T11:29:13.330 に答える
2

同じ関数を複数回エイリアスできることを確認しました。これは私にとって驚きでした。ZendStudio は、関数の最後のエイリアスでのみ「コード支援」を行うように見えますが。

Trait 関数がそれがどのような名前で呼び出されたかを判断できる場合、同じ関数を複数回エイリアスできることは、いくつかの興味深い動作に役立つ可能性があります。しかし、特性関数内で「エイリアス化された」関数を決定できるようには見えません。

ここに私のテストコードがあります:

<?php
trait TestTrait
{
    public function test() { print __CLASS__ . ', ' . __TRAIT__ . ', ' . __METHOD__ . ', ' . __FUNCTION__  . "\n"; }
}
class TestClass
{
    use TestTrait { test as test1; test as test2; }
}
$c = new TestClass();
$c->test1();
$c->test2();

出力:

TestClass, TestTrait, TestTrait::test, test
TestClass, TestTrait, TestTrait::test, test

__ALIAS__おそらく、どのエイリアスとして呼び出されたかを決定するために、特性関数に新しい定数を追加するとよいでしょう。

実際、このための PHP 機能リクエストを作成しました。

https://bugs.php.net/bug.php?id=63629

于 2012-11-27T18:54:35.380 に答える