Мы все знаем, что печально известная ошибка «не может переопределить класс». Есть ли способ преодолеть это и фактически объявить новый класс с тем же именем или это невозможно в PHP 5?
Как заметили Пекка и Техприртер, нет: вы не можете. Однако, если вы используете PHP> = 5.3, вы можете использовать пространства имен и конструкцию «использовать», чтобы эффективно «обновлять» класс. Вот пример:
// MyClass.php класс MyClass { const MY_CONST = 1; }
// MyNamespaceMyClass.php пространство имен Mynamespace; класс MyClass { const MY_CONST = 2; }
// example.php require_once 'MyClass.php'; require_once 'MyNamespaceMyClass.php';
используйте Mynamespace \ MyClass как MyClass;
echo MyClass :: MY_CONST; // выходы 2
Таким образом, у вас есть желаемый результат, так как MyClass теперь ссылается на ваш класс с именами.
Возможно, есть способ использования некоторого неясного расширения, но в базовом стандартном PHP, насколько мне известно, нет.
Тем не менее, вы всегда можете расширить существующий класс и, возможно, в зависимости от вашего сценария – «контрабандой» экземпляр этого расширенного класса в приложение, над которым вы работаете.
Это невозможно. В зависимости от используемого варианта пространства имен, например jpfuentes2, могут работать для вас.
Один взлом – это реализовать пользовательский новый «оператор».
Пример:
$GLOBALS['class_map'] = array('A' => 'A'); function _new($class){ $realClass = $GLOBALS['class_map'][$class]; return new $realClass; }
$GLOBALS['class_map'] = array('A' => 'A'); function _new($class){ $realClass = $GLOBALS['class_map'][$class]; return new $realClass; }
класс A {}
$ a = _new ('A');
// изменение реализации
$ GLOBALS ['class_map'] ['A'] = 'B';
$ a2 = _new ('A');
Другой взлом – использовать runkit для повторного внедрения класса.
Возможно, более современный ответ на 2016 год, похоже, сейчас есть как минимум 3 варианта:
Ссылка: http://php.net/manual/en/function.runkit-class-emancipate.php
bool runkit_class_emancipate ( string $classname )
«Преобразовать унаследованный класс в базовый класс, удаляет любой метод, объем которого является родовым»
Хотя я сам не тестировал это, это кажется жизнеспособным вариантом, если у вас есть контроль над загруженными расширениями. Недостатком здесь будет то, что вы потеряете все предковые методы.
Ссылка: http://php.net/manual/en/function.runkit-method-redefine.php
bool runkit_method_redefine ( string $classname , string $methodname , string $args , string $code [, int $flags = RUNKIT_ACC_PUBLIC ] )
«Динамически изменяет код данного метода»
Это решает проблему варианта 1, если ваша цель – настроить метод или два в базовом классе.
Ссылка: http://php.net/manual/en/function.spl-autoload-register.php
bool spl_autoload_register ([ callable $autoload_function [, bool $throw = true [, bool $prepend = false ]]] )
«Зарегистрировать данную функцию как реализацию __autoload ()»
Это лично моя любимая из 3, потому что:
Это также тот, для которого у меня есть некоторый опыт. Пример реализации следующий:
// Some early point in your application // Ideally after other autoloaders have registered spl_autoload_register('autoload_override'); function autoload_override($class) { if ($class == 'TargetClassName') { include '/path/to/overriding/class.php'; } }
AFAIK, переопределение функций или классов исключений невозможно в PHP.
Если бы вы могли сказать, что вы пытаетесь сделать, может быть, есть другое решение …
В принципе, вы не можете переопределить класс. Но если вы действительно этого хотите, можете. 🙂 Все возможно. Нужен класс, который динамически меняет структуру? Вы можете использовать магический метод __call и состояние шаблона.
class Example { var $state; public function setImplementation($state) { $this->state = $state; } public function __call($method, $args) { if (method_exists($this->state, $method)) return $this->state->$method($args); else // error } }
Существует также набор инструментов PHP для динамического воспроизведения классов: http://php.net/manual/en/book.runkit.php
Я знаю, что класс Rubeclaring и его методы возможны в Ruby (и я считаю это ошибкой в дизайне языка).
В принципе, мы не можем переопределять класс в PHP directly
. Если вам нужно получить redeclare класс в php, я предлагаю вам написать этот класс в отдельном файле и использовать require_one
для вызова этого файла на нужную страницу. Это выглядит так:
page1.php
class abcd { function max() { echo "Hello World!!! count:-".$GLOBALS['x']; } }
page2.php
$i=10; for($x=0;$x<$i;$x++) { require_once "Page1.php"; $myclass = new abcd(); $myclass->max(); }
Теперь он будет работать по вашему желанию . Это сработало для меня .
Выход будет следующим:
Hello World!!! count:- 0 Hello World!!! count:- 1 Hello World!!! count:- 2 Hello World!!! count:- 3 Hello World!!! count:- 4 Hello World!!! count:- 5 Hello World!!! count:- 6 Hello World!!! count:- 7 Hello World!!! count:- 8 Hello World!!! count:- 9