Можно ли использовать mixins в php

Я узнал о mixins.So мое сомнение в том, можно ли использовать mixins в php? Если да, то как?

Использовать Trait введенную в PHP 5.4.

 <?php class Base { public function sayHello() { echo 'Hello '; } } trait SayWorld { public function sayHello() { parent::sayHello(); echo 'World!'; } } class MyHelloWorld extends Base { use SayWorld; } $o = new MyHelloWorld(); $o->sayHello(); ?> 

который печатает Hello World!

http://php.net/manual/en/language.oop5.traits.php

Этот ответ устарел как PHP 5.4. См. Ответ Jeanno о том, как использовать черты .


Это действительно зависит от того, какой уровень mixins вы хотите от PHP. PHP обрабатывает однонаправленное и абстрактное классы, которые могут помочь вам в большей части пути.

Конечно, лучшая часть миксинов заключается в том, что они взаимозаменяемые фрагменты, добавленные в любой класс, который им нужен.

Чтобы обойти проблему множественного наследования, вы можете использовать include для вывода фрагментов кода. Вероятно, вам придется сбрасывать какой-то шаблонный код, чтобы заставить его работать должным образом в некоторых случаях, но это, безусловно, поможет сохранить ваши программы DRY.

Пример:

 class Foo { public function bar( $baz ) { include('mixins/bar'); return $result; } } class Fizz { public function bar( $baz ) { include('mixins/bar'); return $result; } } в class Foo { public function bar( $baz ) { include('mixins/bar'); return $result; } } class Fizz { public function bar( $baz ) { include('mixins/bar'); return $result; } } в class Foo { public function bar( $baz ) { include('mixins/bar'); return $result; } } class Fizz { public function bar( $baz ) { include('mixins/bar'); return $result; } } 

Это не так прямо, как возможность определить класс как class Foo mixin Bar , но он должен получить от вас большую часть пути. Есть некоторые недостатки: вам нужно сохранить те же имена параметров и имена возвращаемых переменных, вам нужно передать другие данные, которые зависят от контекста, такого как func_get_args_array или __FILE__ .

Mixins для PHP (PHP не реализует Mixins изначально, но эта библиотека поможет)

Первый результат google для «php5 mixin»: http://www.sitepoint.com/forums/php-application-design-147/ruby-like-mixins-php5-332491.html

Первый результат Google для «php mixin»: http://www.advogato.org/article/470.html

Короткий ответ: да, но не изначально (все же, очевидно, как отмечает @mchl). Проверьте их.

Более длинный ответ: если вы используете runkit , runkit_method_copy() : «Копирует метод из класса в другой».

Я основывал функции mixins на записи в блоге, найденной в jansch.nl .

 class Node { protected $__decorator_lookup = array(); public function __construct($classes = array()) { foreach($classes as $class) if (class_exists($class)) { $decorator = new $class($this); $methods = get_class_methods($decorator); if (is_array($methods)) foreach($methods as $method) $this->__decorator_lookup[strtolower($method)] = $decorator; } else trigger_error("Tried to inherit non-existant class", E_USER_ERROR); } public function __get($name) { switch($name) { default: if ($this->__decorator_lookup[strtolower($name)]) return $this->__call($name); } } public function __call($method, $args = array()) { if(isset($this->__decorator_lookup[strtolower($method)])) return call_user_func_array(array($this->__decorator_lookup[strtolower($method)], $method), $args); else trigger_error("Call to undefined method " . get_class($this) . "::$method()", E_USER_ERROR); } public function __clone() { $temp = $this->decorators; $this->decorators = array(); foreach($temp as $decorator) { $new = clone($decorator); $new->__self = $this; $this->decorators[] = $new; } } } class Decorator { public $__self; public function __construct($__self) { $this->__self = $__self; } public function &__get($key) { return $this->__self->$key; } public function __call($method, $arguments) { return call_user_func_array(array($this->__self, $method), $arguments); } public function __set($key, $value) { $this->__self->$key = $value; } } class Pretty extends Decorator { public function A() { echo "a"; } public function B() { $this->b = "b"; } } $a = new Node(array("Pretty")); $a->A(); // outputs "a" $a->B(); echo($a->b); // outputs "b" 

РЕДАКТИРОВАТЬ:

  1. Поскольку клон PHP неглубокий, добавлена ​​поддержка __clone.
  2. Кроме того, помните, что unset НЕ будет работать (или, по крайней мере, мне не удалось заставить его работать) в mixin. Итак – делать что-то вроде unset($this->__self->someValue); не будет отменять значение на Node . Не знаю, почему, поскольку теоретически это должно работать. Забавно достаточно unset($this->__self->someValue); var_dump(isset($this->__self->someValue)); unset($this->__self->someValue); var_dump(isset($this->__self->someValue)); будет выдавать правильно false , однако доступ к значению из области Node (как Node->someValue ) будет по-прежнему выдавать true . Там какой-то странный вуду.