Ссылка на класс программно в PHP

Я получаю объект во время некоторого процесса, и этот объект должен выяснить его схему окраски. Например, у меня есть схема раскраски, которая хранится так:

class FirstScheme {
    public static $COLORS = array('1' => 'green', '2' => 'red', ...);
}
class SecondScheme {
    public static $COLORS = array('1' => 'red', '2' => 'green', ...);
}

Я знаю все названия раскрасок заранее; они могут изменяться только при изменении кода. Но схему раскраски, которая будет использоваться для каждого объекта, необходимо определить во время выполнения путем сопоставления атрибута этого объекта.

И здесь я не знаю, что делать. В python я бы определил dict, содержащий сопоставления цветовых схем с именами:

d = {'attr_value1': FirstScheme, 'attr_value2': SecondScheme, 'attr_value3': FirstScheme, ...}

А затем просто получите доступ к переменной "COLORS", потому что она должна быть у каждого класса. Но в PHP нет способа ссылаться на класс таким образом, так как это правильно сделать? Обратите внимание, что несколько атрибутов могут отображаться на одну и ту же схему окраски.

3 ответа

Решение

Если у каждого класса должны быть цвета, определите интерфейс, который позволяет их получить:

interface ColorsProvider {
    function getColors();
}
class FirstScheme implements ColorsProvider {
    public static COLORS = array('1' => 'green', '2' => 'red', ...);

    public function getColors() {
        return self::COLORS;
    }
}
class SecondScheme implements ColorsProvider {
    public static COLORS = array('1' => 'red', '2' => 'green', ...);

    public function getColors() {
        return self::COLORS;
    }
}

Затем, где у вас есть стек ваших параметров:

$a = array(
  'attr_value1' => new FirstScheme(),
  'attr_value2' => new SecondScheme(),
);

Ты можешь позвонить:

$param = 'attr_value1';

if(!isset($a[$param]))
    throw new Exception("undefined param");

if(!($a[$param] instanceof ColorsProvider))
    throw new Exception("Param should point to ColorsProvider");

$a[$param]->getColors();

Пожалуйста, обратите внимание, что это полный объектив. В PHP есть более простые способы получить этот эффект, но мое решение просто элегантно.


Еще один момент - интерфейс полностью разделяет источник цветов. Там будет из файла, базы данных, XML, жестко и т.д.


Реализация по умолчанию может быть:

abstract class DefaultColorsProviderImpl implements ColorsProvider             {
    protected static COLORS = array();

    public function getColors() {
        return self::COLORS;
    }
}

class FirstScheme extends DefaultColorsProviderImpl {
    protected static COLORS = array( ... );
}

Но все же позволяет сделать общую реализацию, которая возвращает цвета из ex из файла.

Альтернативой жесткому кодированию цветов в их собственных классах будет следующий подход:

class ColorScheme {

   protected $colors;

   public function __construct(array $colors) {
       $this->colors = $colors;
   }

   public function getColors() {
       return $this->colors;
   }

}

$scheme1 = new ColorScheme(array('red', 'blue', 'green'));
$scheme2 = new ColorScheme(array('yellow', 'pink', 'cyan'));

Эквивалентом словаря Python в PHP является ассоциативный массив. Так что вы можете сделать это:

$d = array (
    'values_1' => $scheme1->getColors(),
    'values_2' => $scheme2->getColors()
);

Конечно вы можете:

$schemes = [
  'attr_value1' => FirstScheme::$COLORS,
  'attr_value2' => SecondScheme::$COLORS,
  ...
];

Или даже во время выполнения:

$schemes = [
  'attr_value1' => 'FirstScheme',
  'attr_value2' => 'SecondScheme',
  ...
];

А потом:

$reflector = new ReflectionClass($schemes['attr_value1']);
$schema = $reflector->getStaticPropertyValue('COLORS');

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

Другие вопросы по тегам