PHP Любое решение для композиции / наследования, чтобы избежать множественного наследования? - PullRequest
1 голос
/ 23 января 2012

Я пытаюсь решить головоломку с дизайном наиболее эффективным способом, но я склонен перестать думать, что мне действительно нужно множественное наследование. Итак, вот я и спрашиваю плюсы. Я создаю библиотеку с активной записью, которая будет выполнять практически идентичные действия с разными name и value переменными. Я на PHP 5.2.13

Предположим, у меня есть эти классы:

class Property {
    protected $_props = array();

    function set($name, $value) {
        $this->_props[$name] = $value;
    };
}


class ColorProperties extends Property {
    function red($value) {
        $this->set('red', $value);
    }
    function blue($value) {
        $this->set('blue', $value);
    }
}


class LayoutProperties extends Property {
    function x($value) {
        $this->set('x', $value);
    }

    function y($value) {
        $this->set('y', $value);
    }
}

Теперь мне нужно создать класс ShapeProperties, который будет наследоваться как от ColorProperties, так и от LayoutProperties. Так что:

$shape = new ShapeProperties();
$shape->x(10);
$shape->red(255);

Причина, по которой я так нуждаюсь, заключается в автоматическом завершении в IDE с огромным блоком комментариев PHPDoc для каждого свойства. Итак, похоже, что я склоняюсь к копированию / вставке из отчаяния.

СТАРЫЙ ОРГАН (ДО РЕДАКТИРОВАНИЯ)

У меня есть эти классы (блоки):

class Red {
    function red();
}

class LightRed {
    function light_red();
}

class Blue {
    function blue();
}

class LightBlue {
    function light_blue();
}

class Green {
    function green();
}

class LightGreen {
    function light_green();
}

И теперь мне нужно построить множество классов с использованием этих блоков, а именно:

class RGB extends Red, Green, Blue {
    function red();
    function blue();
    function green();
}


class RLRB extends Red, LightRed, Blue {
    function red();
    function light_red();
    function blue();
}

Так что, если я переключу класс слова с интерфейсом, я получу то, что мне нужно, но мне нужна рабочая реализация без загрузки шаблонного кода. Есть ли способ / способ обойти это в PHP?

Ответы [ 2 ]

2 голосов
/ 23 января 2012

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

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

class Color
{
    private $implementations;

    function __construct($implementations)
    {
        $this->implementations = $implementations;
    }

    function __call($functionName, $args)
    {
        foreach ($this->implementations as $impl) {
            $callback = array($impl, $functionName);
            if (is_callable($callback)) {
                return call_user_func_array($callback, $args);
            }
        }

        throw new Exception("Method not found: $functionName");
    }
}


class RGB
{
    function __construct()
    {
        parent::__construct(array(
            new Red,
            new Green,
            new Blue,
        ));
    }
}

$color = new RGB;
$color->red();
1 голос
/ 23 января 2012

В ближайшее время это будет возможно с новой функцией php 5.4 - traits.Это будет выглядеть следующим образом:

trait RED{
  function red(){  };
}

trait BLUE{
  function blue(){  };
}

trait GREEN{
  function green(){  };
}

class RGB{
   use RED,GREEN,BLUE;
}

Но на данный момент лучшим методом, кажется, являются использование статических методов и инъекций зависимостей, например:

class RED{
    static function get_red($obj){
        return '0x'.dechex($obj->red);
    }
}

class RGB{
    public $red;
    public $green;
    public $blue;
    public function __construct($r,$g,$b){
        $this->red = $r;
        $this->green = $g;
        $this->blue = $b;
    }
    public function get_red(){
        return RED::get_red($this);
    }
}

$rgb = new RGB(255,255,255);
echo $rgb->get_red(); 

, но вы все равно должны объявитьвсе функции и заставить его вызывать метод из другого класса.

...