Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

Используйте 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

Ответ 2

Этот ответ устарел как PHP 5.4. См. ответ Jeanno для использования признаков.


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

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

Чтобы обойти проблему множественного наследования, вы можете использовать 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 mixin Bar, но он должен получить от вас большую часть пути. Есть некоторые недостатки: вам нужно сохранить те же имена параметров и имена возвращаемых переменных, вам нужно передать другие данные, которые зависят от контекста, например func_get_args_array или __FILE__.

Ответ 3

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

Ответ 4

Первый результат 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, checkout runkit_method_copy(): "Копирует метод из класса в другой".

Ответ 5

Я основывал функции 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"

ИЗМЕНИТЬ:

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