Как будто вы пытаетесь получить доступ к объекту, который является null
. Рассмотрим ниже пример:
TypeA objA;
. В это время вы только что объявили этот объект, но не инициализировали или не инициализировали. И всякий раз, когда вы пытаетесь получить доступ к каким-либо свойствам или методам в нем, он будет генерировать NullPointerException
, что имеет смысл.
См. Также этот пример:
String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
Одна из проблем с разрешением во время выполнения - то, что Вы делаете его действительно трудно для кэшей кода операции (как APC). Однако, на данный момент выполнение чего-то как Вы описывает в Вашем вопросе, допустимый путь, если Вам нужно определенное количество косвенности, когда instanciating наполняют.
Пока Вы не делаете чего-то как
$classname = 'SomeClassName';
for ($x = 0; $x < 100000; $x++){
$object = new $classname;
}
Вы, вероятно, в порядке :-)
(мое точка быть: Динамично поиск класса здесь и затем не причиняет боль. Если Вы будете часто делать это, то это будет).
Кроме того, убедитесь, что $classname никогда не может устанавливаться с внешней стороны - Вы хотели бы иметь некоторый контроль над тем, какого точного класса Вы будете инстанцировать.
Выглядит, что можно все еще передать аргументы конструктору, вот мой тестовый код:
<?php
class Test {
function __construct($x) {
echo $x;
}
}
$class = 'Test';
$object = new $class('test'); // echoes "test"
?>
Именно это Вы имели в виду, правильно?
Так единственная другая проблема Вы упомянули и что я могу думать, безопасность его, но не должно быть слишком трудно заставить его защитить, и это, очевидно, намного более безопасно, чем использование оценки ().
Я добавил бы, что Вы можете также instanciate он с динамическим количеством использования параметров:
<?php
$class = "Test";
$args = array('a', 'b');
$ref = new ReflectionClass($class);
$instance = $ref->newInstanceArgs($args);
?>
Но конечно Вы добавляете еще некоторые, служебные путем выполнения этого.
О проблеме безопасности я не думаю, что она имеет значение очень, по крайней мере, это - ничто по сравнению с оценкой (). В худшем случае неправильный класс получает instanciated, конечно, это - потенциальное нарушение защиты, но намного тяжелее использовать, и легко отфильтровать использование массива позволенных классов при реальной необходимости во вводе данных пользователем для определения имени класса.
Я использую динамическое инстанцирование в своей пользовательской платформе. Мой контроллер приложения должен инстанцировать подконтроллера на основе запроса, и было бы просто смешно использовать гигантский, постоянно меняющийся оператор переключения для управления загрузкой тех контроллеров. В результате я могу добавить контроллер после контроллера к моему приложению, не имея необходимость изменять контроллер приложения для вызова их. Пока мои URIs придерживаются конвенций моей платформы, контроллер приложения может использовать их, не имея необходимость знать что-либо до времени выполнения.
Я использую эту платформу в производственном приложении корзины покупок прямо сейчас, и производительность довольно благоприятна, также. Однако я только использую динамический выбор класса в одном или двух местах в целом приложении. Интересно, при каких обстоятельствах необходимо было бы часто использовать его, и являются ли те ситуации, которые страдают от требования программиста сверхабстрагировать приложение (я был виновен в этом прежде).
@coldFlame: IIRC можно использовать call_user_func(array($className, 'someStaticMethod')
и call_user_func_array()
передать параметрические усилители
class Test {
function testExt() {
print 'hello from testExt :P';
}
function test2Ext()
{
print 'hi from test2Ext :)';
}
}
$class = 'Test';
$method_1 = "testExt";
$method_2 = "test2Ext";
$object = new $class(); // echoes "test"
$object->{$method_2}(); // will print 'hi from test2Ext :)'
$object->{$method_1}(); // will print 'hello from testExt :P';
этот прием работы и в php4 и в php5 :D обладает..
Одна проблема состоит в том, что Вы не можете обратиться к статическим участникам как этот, например
<?php
$className = 'ClassName';
$className::someStaticMethod(); //doesn't work
?>
Может действительно быть хит производительности для того, чтобы иметь необходимость разрешить название переменной перед поиском определения класса. Но, не объявляя классы динамично у Вас нет реального способа сделать программирование "dyanmic" или "meta". Вы не смогли бы записать программы генерации кода или что-либо как проблемно-ориентированная конструкция языка.
Мы используем эту конвенцию повсеместно в некоторых базовых классах нашей внутренней платформы для создания URL к работе отображений контроллера. Я также видел его во многих коммерческих приложениях с открытым исходным кодом (я попытаюсь вырыть для примера и отправить его). Так или иначе точка моего ответа - то, что кажется определенно стоящим того, что является, вероятно, небольшим снижением производительности, если это делает более гибкий, динамический код.
Другой компромисс, который я должен упомянуть, тем не менее, - то, что производительность в стороне, это действительно делает код немного менее очевидным и читаемым, если Вы не очень осторожны со своими именами переменной. Большая часть кода написана однажды, и перечитана и много раз изменяется, таким образом, удобочитаемость важна.
Alan, нет ничего неправильно с динамической инициализацией класса. Эта техника присутствует также на языке Java, где можно преобразовать строку в использование класса Class.forClass('classname')
метод. Также довольно удобно задержать сложность алгоритма к нескольким классам вместо того, чтобы иметь список если-условий. Динамические имена классов особенно хорошо подходят в ситуациях, где Вы хотите, чтобы Ваш код остался открытым для расширения без потребности в модификациях.
Я сам часто использую различные классы в сочетании с таблицами базы данных. В одном столбце я сохраняю имя класса, которое будет использоваться для обработки записи. Это дает мне великую державу добавления новых типов записей, и обработайте их уникальным способом, не изменяя единственный байт в существующем коде.
Вы не должны быть обеспокоены производительностью. Это не имеет почти никаких издержек, и сами объекты супер быстры в PHP. Если необходимо породить тысячи одинаковых объектов, используйте шаблон разработки В наилегчайшем весе для сокращения объема потребляемой памяти. Особенно, Вы не должны жертвовать своим временем как разработчик только для сохранения миллисекунд на сервере. Также оптимизаторы кода операции работают беспрепятственно с этой техникой. Сценарии, скомпилированные с Оптимизатором Зенда, не неправильно себя вели.