Я хотел бы повторно использовать функциональность несколько раз в одном классе. Эта функция зависит от частной переменной:
trait Address { private $address; public function getAddress() { return $this->address; } public function setAddress($address) { $this->address = $address; } }
Единственный способ, с помощью которого я дважды использовал эту черту , заключается в следующем:
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
Есть ли решение действительно использовать этот признак дважды, не разделяя его частных переменных?
Объявление признака с use
не создаст экземпляр этой черты. Черты – это просто код, который копируется и вставляется в класс использования. Как только будет создан псевдоним для этого метода, например, он добавит что-то вроде
public function getHomeAddress() { return $this->getAddress(); }
к вашему классу User. Но это будет только одна черта. Не будет двух разных $address
свойств, но только одного.
Вы можете сделать методы частными, а затем делегировать любые публичные вызовы ему через __call
помощью switch / __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 … } } }
Но это всего лишь банда червей.
Другими словами, вы не можете разумно делать то, что вы пытаетесь сделать с чертами. Либо используйте две разные черты. Или используйте хорошую старую агрегацию и добавьте конкретные прокси-методы.
Я подтвердил, что вы можете использовать одну и ту же функцию несколько раз, что было для меня неожиданностью. Несмотря на то, что 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-запрос функции для этого:
я могу немного опоздать на вечеринку, но поведение, которое вы пытаетесь создать, не является чем-то, что должно быть покрыто чертой, а простой композицией объекта.
<?php class Adddress { private $street; private $number; public function __construct(string $street, ?string $number) {} public function street() : string {} public function number() : string {} } class User { private $homeAddress; private $workAddress; public function getHomeAddress() : Address {} public function setHomeAddress(Address $homeAddress) : self {} public function getWorkAddress() : Address {} public function setWorkAddress(Address $workAddress) : self {} }