Каким-либо образом действительно ли возможно создать экземпляр php класса, не вызывая его конструктора?
У меня есть Класс A и в то время как создание экземпляра его передает файл, и в конструкторе Class A открываю файл.
Теперь в Классе A, существует функция, которую я должен вызвать, но не обязан передавать файл и таким образом, нет потребности использовать функциональность конструктора вводного файла, как не передаю файл.
Таким образом, мой вопрос, действительно ли возможно каким-либо образом создать экземпляр класса PHP, не вызывая его конструктора?
Обратите внимание, что я не могу сделать функциональные помехи, как использую некоторые свойства класса в функции.
Конструктор классов будет вызываться всегда. Однако есть несколько способов обойти это.
Первый способ - предоставить значения по умолчанию для ваших параметров в конструкторе и выполнять определенные действия с этими параметрами только в том случае, если они установлены. Например:
class MyClass {
public __construct($file = null) {
if ($file) {
// perform whatever actions need to be done when $file IS set
} else {
// perform whatever actions need to be done when $file IS NOT set
}
// perform whatever actions need to be done regardless of $file being set
}
}
Другой вариант - расширить ваш класс таким образом, чтобы конструктор дочернего класса не вызывал конструктор родительского класса.
class MyParentClass {
public __construct($file) {
// perform whatever actions need to be done regardless of $file being set
}
}
class MyChildClass extends MyParentClass {
public __construct() {
// perform whatever actions need to be done when $file IS NOT set
}
}
Примечание. Приведенное ниже решение предназначено для PHP 5.3 и ниже. Начиная с PHP 5.4, вы также можете сделать это через Reflection, как показано в другом месте на этой странице .
Это действительно возможно.
Изменено из PHPUnit_Framework_MockObject_Generator
1 $myClass = unserialize(
2 sprintf(
3 'O:%d:"%s":0:{}',
4 strlen('MyClass'), 'MyClass'
5 )
6 );
Имейте в виду, что подобный код хорош и оправдан в такой среде, как PHPUnit.Но если вам нужен такой код в вашем производственном коде, вы, вероятно, делаете что-то очень странное.
Поскольку вы просили объяснения:
Когда вы сериализуете объект , вы получаете строковое представление объекта. Например,
echo serialize(new StdClass) // gives O:8:"stdClass":0:{}
O
означает объект. 8
- длина строки имени класса. "stdClass"
- это, очевидно, имя класса. Сериализованный объект имеет набор свойств 0
( больше, чем позже ), обозначенных пустыми фигурными скобками. :
- это просто разделители.
Каждой сериализованной строке можно воссоздать ее исходное «живое» значение с помощью функции unserialize . Это обойдёт конструктор. Как правильно указал Чарльз, магический метод __ wakeup ()
будет вызываться, если он определен (точно так же, как __ sleep ()
будет вызываться при сериализации).
В строке 3 вы видите строку, подготовленную для использования с sprintf (строка 2). Как вы можете видеть, длина строки имени класса задается как % d
, а имя класса - как % s
. Это должно сказать sprintf, что он должен использовать первый аргумент, переданный ему в строке 4, как цифру, а второй - как строку. Следовательно, результатом вызова sprintf будет
'O:7:"MyClass":0:{}'
. Вы должны заменить оба вхождения «MyClass» в строке 4 на желаемое имя класса, чтобы создать сериализованную строку класса, который вы хотите создать, без вызова контроллера.
Затем эта строка десериализуется в экземпляр MyClass в строке 1, минуя конструктор. Несериализованный экземпляр будет иметь все методы своего класса, а также любые свойства. Если в MyClass есть свойства, они будут иметь значения по умолчанию, если вы не добавите другие значения в сериализованную фиктивную строку.
И это уже все. Ничего особенного в этом нет.
Не лучше ли сделать нужную функцию статической - изменить класс A так, чтобы у него был другой конструктор, который не требует никаких дополнительных действий
Если класс имеет функцию, которая не имеет доступа ни к одному из нестатических свойств или функций в классе, ее можно сделать статической.
class A{
public function __construct($arg1){
}
public static function foo(){
//do something that doesn't involve the class properties
}
}
Затем ее можно вызвать без создания класса
//the constructor will not be called as we haven't created an instance of A
A::foo();
Разница между статической и не статической функцией состоит в том, что статическая функция не может получить доступ к свойствам класса функций, которые также являются статическими. Итак, если в foo ()
у вас есть какой-либо код, который использует $ this ->
, вы не можете сделать его статическим.
вы можете сделать метод статическим и вызывать его из контекста класса, а не из контекста объекта.
в коде это будет выглядеть так:
class A {
public static function func($txt) {
print($txt);
}
}
A::func('test');