Строители и деструкторы
PHP позволяет разработчикам объявлять методы конструктора для классов.Классы,имеющие метод конструктора,вызывают этот метод на каждом вновь созданном объекте,поэтому он подходит для любой инициализации,которая может потребоваться объекту перед его использованием.
Примечание . Родительские конструкторы не вызываются неявно, если дочерний класс определяет конструктор. Для запуска родительского конструктора требуется вызов parent :: __ construct () внутри дочернего конструктора. Если дочерний элемент не определяет конструктор, он может быть унаследован от родительского класса, как обычный метод класса (если он не был объявлен как закрытый).
Пример # 1 Конструкторы в наследовании
class BaseClass < function __construct( ) < print "In BaseClass constructor\n"; > > class SubClass extends BaseClass < function __construct( ) < parent::__construct(); print "In SubClass constructor\n"; > > class OtherSubClass extends BaseClass < // inherits BaseClass's constructor > // In BaseClass constructor $obj = new BaseClass(); // In BaseClass constructor // In SubClass constructor $obj = new SubClass(); // In BaseClass constructor $obj = new OtherSubClass(); ?>
В отличие от других методов, __construct () освобождается от обычных правил совместимости подписей при расширении.
Конструкторы-это обычные методы,которые вызываются во время инстанцирования соответствующего объекта.Как таковые,они могут определять произвольное количество аргументов,которые могут быть обязательными,могут иметь тип и значение по умолчанию.Аргументы конструктора вызываются путем помещения аргументов в круглые скобки после имени класса.
Пример # 2 Использование аргументов конструктора
class Point < protected int $x; protected int $y; public function __construct(int $x, int $y = 0) < $this->x = $x; $this->y = $y; > > // Pass both parameters. $p1 = new Point(4, 5); // Pass only the required parameter. $y will take its default value of 0. $p2 = new Point(4); // With named parameters (as of PHP 8.0): $p3 = new Point(y: 5, x: 4); ?>
Если класс не имеет конструктора,или конструктор не имеет необходимых аргументов,круглые скобки можно опустить.
Old-style constructors
До PHP 8.0.0 классы в глобальном пространстве имен будут интерпретировать метод, названный так же, как класс, как конструктор старого стиля. Этот синтаксис устарел и приведет к ошибке E_DEPRECATED , но по-прежнему вызовет эту функцию как конструктор. Если определены и __construct (), и одноименный метод, будет вызываться __construct () .
В классах с разграничением имен,или в любом классе,начиная с PHP 8.0.0,метод,названный так же,как и класс,никогда не имеет никакого особого значения.
Всегда используйте __construct () в новом коде.
Constructor Promotion
Начиная с PHP 8.0.0,параметры конструктора также могут быть повышены,чтобы соответствовать свойству объекта.Очень часто бывает,что параметры конструктора присваиваются свойству в конструкторе,но при этом не используются.Продвижение конструктора обеспечивает краткое описание этого случая.Приведенный выше пример можно переписать следующим образом.
Пример # 3 Использование продвижения свойства конструктора
class Point < public function __construct(protected int $x, protected int $y = 0) < >>
Если аргумент конструктора включает модификатор видимости,PHP интерпретирует его как свойство объекта и аргумент конструктора и присваивает свойству значение аргумента.Тело конструктора может быть пустым или содержать другие утверждения.Любые дополнительные утверждения будут выполнены после того,как значения аргументов будут присвоены соответствующим свойствам.
Не все аргументы должны быть продвинутыми.Можно смешивать и сочетать продвигаемые и непродвигаемые аргументы в любом порядке.Продвинутые аргументы не влияют на код,вызывающий конструктор.
Note:
Свойства объекта не могут быть типизированы для вызова из-за неоднозначности движка. Следовательно, продвинутые аргументы также не могут быть типизированными вызываемыми . Однако разрешено объявление любого другого типа .
Note:
Атрибуты, помещенные в аргумент продвинутого конструктора, будут реплицированы как в свойство, так и в аргумент.
Новое в инициализаторах
Начиная с PHP 8.1.0, объекты можно использовать в качестве значений параметров по умолчанию, статических переменных и глобальных констант, а также в качестве аргументов атрибутов. Теперь объекты также можно передавать в функцию define() .
Note:
Использование динамического или нестрокового имени класса или анонимного класса не допускается.Использование распаковки аргументов не допускается.Использование неподдерживаемых выражений в качестве аргументов не допускается.
Пример #4 Использование new в инициализаторах
// All allowed: static $x = new Foo; const C = new Foo; function test($param = new Foo) <> #[AnAttribute(new Foo)] class Test < public function __construct( public $prop = new Foo, ) <> > // All not allowed (compile-time error): function test( $a = new (CLASS_NAME_CONSTANT)( ), // dynamic class name $b = new class <>, // anonymous class $c = new A(. []), // argument unpacking $d = new B($abc), // unsupported constant expression ) <> ?>
Методы создания статики
PHP поддерживает только один конструктор для каждого класса.В некоторых случаях,однако,может быть желательно позволить объекту быть сконструированным различными способами с различными входными данными.Рекомендуемый способ сделать это-использовать статические методы в качестве оберток конструкторов.
Пример #5 Использование статических методов создания
class Product < private ?int $id; private ?string $name; private function __construct(?int $id = null, ?string $name = null) < $this->id = $id; $this->name = $name; > public static function fromBasicData(int $id, string $name): static < $new = new static($id, $name); return $new; > public static function fromJson(string $json): static < $data = json_decode($json); return new static($data['id'], $data['name']); > public static function fromXml(string $xml): static < // Custom logic here. $data = convert_xml_to_array($xml); $new = new static(); $new->id = $data['id']; $new->name = $data['name']; return $new; > > $p1 = Product::fromBasicData(5, 'Widget'); $p2 = Product::fromJson($some_json_string); $p3 = Product::fromXml($some_xml_string);
Конструктор можно сделать приватным или защищенным,чтобы предотвратить его вызов извне.В этом случае только статический метод сможет инстанцировать класс.Поскольку они находятся в одном и том же определении класса,они имеют доступ к приватным методам,даже если они не относятся к одному и тому же экземпляру объекта.Частный конструктор является необязательным и может иметь или не иметь смысл в зависимости от случая использования.
Затем три публичных статических метода демонстрируют различные способы инстанцирования объекта.
- fromBasicData() принимает точные необходимые параметры, затем создает объект, вызывая конструктор и возвращая результат.
- fromJson() принимает строку JSON и сама выполняет некоторую предварительную обработку, чтобы преобразовать ее в формат, желаемый конструктором. Затем он возвращает новый объект.
- fromXml() принимает строку XML, предварительно обрабатывает ее, а затем создает пустой объект. Конструктор по-прежнему вызывается, но, поскольку все параметры являются необязательными, метод их пропускает. Затем он присваивает значения свойствам объекта непосредственно перед возвратом результата.
Во всех трех случаях ключевое слово static транслируется в имя класса, в котором находится код. В данном случае Product .
Destructor
PHP обладает концепцией деструктора,схожей с концепцией деструктора в других объектно-ориентированных языках,таких как C++.Метод деструктора будет вызван,как только не останется других ссылок на конкретный объект,или в любом порядке во время последовательности выключения.
Пример #6 Пример деструктора
class MyDestructableClass < function __construct( ) < print "In constructor\n"; > function __destruct( ) < print "Destroying " . __CLASS__ . "\n"; > > $obj = new MyDestructableClass();
Как и конструкторы, родительские деструкторы не будут вызываться механизмом неявно. Чтобы запустить родительский деструктор, нужно явно вызвать parent :: __ destruct () в теле деструктора. Также, как и конструкторы, дочерний класс может наследовать деструктор родителя, если он сам не реализует его.
Деструктор будет вызываться, даже если выполнение скрипта остановлено с помощью exit () . Вызов exit () в деструкторе предотвратит выполнение оставшихся подпрограмм выключения.
Note:
Деструкторы,вызываемые во время завершения работы скрипта,уже отправили заголовки HTTP.Рабочая директория на этапе завершения работы скрипта может отличаться при использовании некоторых SAPI (например,Apache).
Note:
Попытка бросить исключение из деструктора (вызывается во время завершения работы скрипта)приводит к фатальной ошибке.
PHP 8.2
Создание копии объекта с полностью реплицированными свойствами не всегда является желаемым поведением.
Ключевое слово final не позволяет дочерним классам переопределять константу метода,префикснув определение с Пример #1 Final methods Пример #2 Final class Примечание:
Наследование-это хорошо известный принцип программирования,и PHP использует его в своей объектной модели.