Ссылка на класс программно в 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');
Но это, кажется, совсем не обслуживаемо, и вы хотели бы хранить такую информацию в надлежащем слое данных, без жесткого кодирования их как статических полей класса [что не является их целью].