Mixins in PHP

Комментарии к статье
«Mixins in PHP»

Не буду распространяться, что такое Mixins — об этом уже много и восторженно написано. Проблема в том, что PHP напрямую не поддерживает примеси, но есть несколько способов решения задачи. Те, что находятся в интернете используют eval... Мы пойдем иным путем. Есть ведь магические методы типа __call(), __get() и __set()


***

Вот немного переделал под php 5.3
теперь можно вызывать статические методы подмешиваемого класса.

<?php

abstract class Mixin {
private $clr;

public function __construct($caller) {
$this->clr = $caller;
}

public function __get($prop) {
return $this->clr->__access_get_prop($prop);
}


public function __set($prop, $value) {
return $this->clr->__access_set_prop($prop, $value);
}


public function __call($method, $args) {
return $this->clr->__access_call($method, $args);
}
}

abstract class Caller {
private $mixins = array(); // массив экземпляров примсей

public function __call($method, $args) {
foreach ($this->mixins as $cname => $co) {
if (method_exists($co, $method)) {
return call_user_func_array(array($co, $method), $args);
}
}
throw new Exception("call to unfdefined method " . $method);
}

public static function __callStatic($method, $args){
if (isset(static::$mixins)){
foreach (static::$mixins as $cname) {
if (method_exists($cname, $method)) {
return call_user_func_array(array($cname, $method), $args);
}
}
}
throw new Exception("call to unfdefined static method " . $method);
}

public function __access_get_prop($prop) {
if (property_exists($this, $prop)) {
return $this->$prop;
}
}

public function __access_set_prop($prop, $value) {
if (property_exists($this, $prop)) {
return $this->$prop = $value;
}
}

public function __access_call($method, $args) {
if (method_exists($this, $method)) {
return call_user_func_array(array($this, $method), $args);
}
}

public function mixin($classes){
if (!is_array($classes)) $classes = array($classes);
foreach ($classes as $class){
$this->mixins[$class] = new $class($this);
}
}
}


/*
* использование
*/

// конкретная примесь с присущим ей функционалом
class SayHello extends Mixin {
public function say() {
return "Hello " . $this->name;
}

public function sayLoud() {
return 'Hello ' . $this->loud() . '!!!';
}

public function addPrefix() {
$this->name = "Mr. " . $this->name;
}

public static function testStatic(){
return '<p>это статик функция</p>';
}
}

// конкретный родительский класс, расширенный примесью
class Person extends Caller {
static $mixins = array('SayHello');
public $name;

function __construct($name) {
$this->name = $name;
$this->mixin('SayHello');
}

public function loud() {
return '<b>' . $this->name . '</b>';
}

public function saySomething() {
$this->addPrefix();
return '<h2>' . $this->name . '</h2>';
}

}

$p = new Person("Schleicher");

echo $p->say(); // Hello Schleicher
echo $p->sayLoud(); // Hello <b>Schleicher</b>!!!
echo $p->saySomething(); // <h2>Mr. Schleicher</h2>
echo $p->testStatic();

Михаил (2.05.2010)

Реализовал свою небольшую библиотеку для примесей. Быстродействие, в принципе, приемлемое:

http://ru.fractalizer.ru/frpost_128/

FractalizeR (7.11.2010)

Отличная модель, спасибо! Я написал точно такую же модель (после знакомства с примесями в википедии), только без __access_get/set_prop (спасибо за подсказку).

Но, меня очень интересует именно целесообразность использования примесей. Можно ведь с помощью делегирования добиться такого же code reuse (не совсем прям такого же, но более нативного и прозрачного). Mixins выглядят более логично, а делегирование - проще и безопаснее.
Подскажите Ваше мнение по этой дилемме, пожалуйста.

OZ (11.11.2010)

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

schleicher (11.11.2010)

Отсутствие грамотно оформленного кода говорит нам о пренебрежительном отношении автора к материалу и читателям

Блабла (13.11.2010)

Отлично! Спасибо, действительно очень просто и доступно.
зы: Блабла, ваш пост говорит о том, что вы зря зашли на эту страницу.

Alex-an (13.11.2010)

Check out ClassMixer: https://github.com/wellsprin...dwide/PHP-ClassMixer

Anthony (16.12.2010)

добавить комментарий
Имя
e-mail
URL
Комментарий
Самизнаетечто

mem: 1257 total: 17 module: 7 xsl: 7