Создание экземпляров класса без дополнительных круглых скобок
Функция «доступа к членам класса при создании экземпляра» была представлена в PHP 5.4.0. С тех пор константы, свойства и методы могут быть доступны во вновь созданном экземпляре без промежуточной переменной, но только если выражение new заключено в круглые скобки:
class Request implements Psr\Http\Message\RequestInterface
{
// ...
}
// OK
$request = (new Request())->withMethod('GET')->withUri('/hello-world');
// PHP Parse error: syntax error, unexpected token "->"
$request = new Request()->withMethod('GET')->withUri('/hello-world');
Этот RFC позволяет опускать круглые скобки вокруг new выражения со скобками аргументов конструктора и написать просто new Class()->method():
new Request()->withMethod('GET')->withUri('/hello-world');
Возьмем для примера класс:
class MyClass
{
const CONSTANT = 'constant';
public static $staticProperty = 'staticProperty';
public static function staticMethod(): string { return 'staticMethod'; }
public $property = 'property';
public function method(): string { return 'method'; }
public function __invoke(): string { return '__invoke'; }
}
Так можно теперь написать:
var_dump(
new MyClass()::CONSTANT, // string(8) "constant"
new MyClass()::$staticProperty, // string(14) "staticProperty"
new MyClass()::staticMethod(), // string(12) "staticMethod"
new MyClass()->property, // string(8) "property"
new MyClass()->method(), // string(6) "method"
new MyClass()(), // string(8) "__invoke"
);
Или:
$myClass = MyClass::class;
var_dump(
new $myClass()::CONSTANT, // string(8) "constant"
new $myClass()::$staticProperty, // string(14) "staticProperty"
new $myClass()::staticMethod(), // string(12) "staticMethod"
new $myClass()->property, // string(8) "property"
new $myClass()->method(), // string(6) "method"
new $myClass()(), // string(8) "__invoke"
);
var_dump(
new (trim(' MyClass '))()::CONSTANT, // string(8) "constant"
new (trim(' MyClass '))()::$staticProperty, // string(14) "staticProperty"
new (trim(' MyClass '))()::staticMethod(), // string(12) "staticMethod"
new (trim(' MyClass '))()->property, // string(8) "property"
new (trim(' MyClass '))()->method(), // string(6) "method"
new (trim(' MyClass '))()(), // string(8) "__invoke"
);
Стоит также учитывать, что данный RFC не меняет поведение new выражений без круглых скобок аргументов конструктора:
new MyClass::CONSTANT; // продолжит выдавать синтаксическую ошибку
new $myClass::CONSTANT; // продолжит выдавать синтаксическую ошибку
new MyClass::$staticProperty; // продолжит работать как `new (MyClass::$staticProperty)`
new $myClass::$staticProperty; // продолжит работать как `new ($myClass::$staticProperty)`
new $myObject->property; // продолжит работать как `new ($myObject->property)`
Так же этот RFC позволяет опускать круглые скобки вокруг new выражения анонимного класса независимо от того, присутствуют ли круглые скобки в аргументах конструктора:
var_dump(
// string(8) "constant"
new class { const CONSTANT = 'constant'; }::CONSTANT,
// string(14) "staticProperty"
new class { public static $staticProperty = 'staticProperty'; }::$staticProperty,
// string(12) "staticMethod"
new class { public static function staticMethod() { return 'staticMethod'; } }::staticMethod(),
// string(8) "property"
new class { public $property = 'property'; }->property,
// string(6) "method"
new class { public function method() { return 'method'; } }->method(),
// string(8) "__invoke"
new class { public function __invoke() { return '__invoke'; } }(),
);
В заключении можно сказать, что некоторые языки, такие как Kotlin, позволяют создавать экземпляры классов с помощью выражения MyClass()
. Опустить ключевое слово new
в PHP на данный момент невозможно, поскольку классы и функции могут иметь одно и то же имя (в Kotlin это невозможно). Итак, чтобы добиться этого в PHP, надо сначала отказаться от объявления функций и классов с одинаковыми именами.
Спасибо Валентину Удальцову за вклад по улучшению синтаксиса PHP.
Что думаешь?