В PHP действительно ли возможно создать экземпляр класса, не вызывая конструктора класса?

Каким-либо образом действительно ли возможно создать экземпляр php класса, не вызывая его конструктора?

У меня есть Класс A и в то время как создание экземпляра его передает файл, и в конструкторе Class A открываю файл.

Теперь в Классе A, существует функция, которую я должен вызвать, но не обязан передавать файл и таким образом, нет потребности использовать функциональность конструктора вводного файла, как не передаю файл.

Таким образом, мой вопрос, действительно ли возможно каким-либо образом создать экземпляр класса PHP, не вызывая его конструктора?

Обратите внимание, что я не могу сделать функциональные помехи, как использую некоторые свойства класса в функции.

16
задан Rachel 31 March 2010 в 19:50
поделиться

4 ответа

Конструктор классов будет вызываться всегда. Однако есть несколько способов обойти это.

Первый способ - предоставить значения по умолчанию для ваших параметров в конструкторе и выполнять определенные действия с этими параметрами только в том случае, если они установлены. Например:

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
    }
}
12
ответ дан 30 November 2019 в 15:40
поделиться

Примечание. Приведенное ниже решение предназначено для 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 есть свойства, они будут иметь значения по умолчанию, если вы не добавите другие значения в сериализованную фиктивную строку.

И это уже все. Ничего особенного в этом нет.

13
ответ дан 30 November 2019 в 15:40
поделиться

Не лучше ли сделать нужную функцию статической - изменить класс 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 -> , вы не можете сделать его статическим.

2
ответ дан 30 November 2019 в 15:40
поделиться

вы можете сделать метод статическим и вызывать его из контекста класса, а не из контекста объекта.

в коде это будет выглядеть так:

class A {
  public static function func($txt) {
    print($txt);
  }
}

A::func('test');
-1
ответ дан 30 November 2019 в 15:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: