- Возвращаемый тип self и static в интерфейсах PHP
- Проблема с self
- Возвращаемый тип static
- Когда использовать static?
- Текучие интерфейсы
- Неизменяемые классы
- Порождающие статические методы
- Интерфейсы для «одиночек»
- Заключение
- Get Class Name in PHP
- Use Class Name Resolution to Get Class Name in PHP
- Use __CLASS__ Constant to Get Class Name in PHP
- Use get_class() Function to Get Class Name in PHP
- Use Reflection Class to Get Class Name in PHP
- Use ::class on Object to Get Class Name in PHP
- Related Article — PHP Class
Возвращаемый тип self и static в интерфейсах PHP
Очень популярная история в PHP, когда метод объекта возвращает сам объект или новый экземпляр того же самого объекта. В этом случае мы указываем тип результата self и всё отлично работает. Например:
final class Car < public function __construct( private ?string $color = null, ) < >public function withColor(string $color): self < $new = clone $this; $new->color = $color; return $new; > >
С финальными классами это действительно гарантированно работает. Но в случае с интерфейсами (а также с не финальными классами, абстрактными классами и трейтами, но в этой статьей рассмотрим только интерфейсы) появляется не очевидная на первый взгляд проблема.
Проблема с self
Допустим у нас есть два интерфейса. Объекты, которые их реализуют, позволяют указать цвет и имя соответственно:
interface ColorableInterface < public function setColor(string $color): self; >interface NameableInterface
И мы решили сделать некий конфигуратор для объектов, реализующих оба интерфейса:
final class Configurator < public function configure( ColorableInterface&NameableInterface $object, string $color, string $name ): void < $object->setColor($color)->setName($name); > >
И вроде бы всё хорошо, но если прогнать этот код, к примеру, через статический анализатор Psalm, то мы получим ошибку «Method ColorableInterface::setName does not exist» («Метод ColorableInterface::setName не существует»).
И действительно, Psalm не ошибся. Интерфейс ColorableInterface гарантирует, что метод setColor() вернёт self , то есть объект, реализующий ColorableInterface , и ничего более, а метода setName() в интерфейсе ColorableInterface нет.
Пример объекта, реализующего оба интерфейса, но при этом не готового для использования в конфигураторе из предыдущего примера:
final class CustomColor implements ColorableInterface < private string $color = ''; public function setColor(string $color): self < $this->color = $color; return $this; > > final class CustomName implements NameableInterface < private string $name = ''; public function setName(string $name): self < $this->name = $name; return $this; > > final class StrangeObject implements ColorableInterface, NameableInterface < public function setColor(string $color): ColorableInterface < return new CustomColor(); >public function setName(string $name): NameableInterface < return new CustomName(); >>
Возвращаемый тип static
В PHP 8.0 появилась возможность указать в качестве результата выполнения метода тип static , который на уровне языка гарантирует, что метод вернёт экземпляр того же самого класса, в котором он вызван.
Теперь мы можем переписать интерфейсы следующим образом:
interface ColorableInterface < public function setColor(string $color): static; >interface NameableInterface
И это решит описанную выше проблему.
Когда использовать static?
Как правило, static используется в следующих ситуациях.
Текучие интерфейсы
Текучий интерфейс — структурный шаблон проектирования, позволяющий создавать более читабельный код. Фактически, это возможность вызова методов «цепочкой».
Неизменяемые классы
Неизменяемый (иммутабельный) класс — это класс, который после создания не меняет своего состояния, то есть он не содержит сеттеров и публичных изменяемых свойств. Но такие классы могут содержать методы (обычно они имеют префикс with ), позволяющие получить клон объекта с изменённым состоянием. Как раз для таких методов в интерфейсах необходимо использовать тип static .
interface ReadableInterface
Порождающие статические методы
Статические методы, позволяющие создать экземпляр объекта текущего класса.
Интерфейсы для «одиночек»
Интерфейс, определяющий метод для реализации шаблона проектирования «Одиночка» (метод предоставляющий доступ к единственному экземпляру объекта в приложении и запрещающий повторное создание этого объекта).
Заключение
Таким образом, при проектировании интерфейсов в PHP мы можем сразу заложить, что ожидаем увидеть в качестве результата выполнения метода:
- self — любой объект, который реализует данный интерфейс;
- static — экземпляр объекта того же класса, что и объект в котором вызван метод.
Get Class Name in PHP
- Use Class Name Resolution to Get Class Name in PHP
- Use __CLASS__ Constant to Get Class Name in PHP
- Use get_class() Function to Get Class Name in PHP
- Use Reflection Class to Get Class Name in PHP
- Use ::class on Object to Get Class Name in PHP
This tutorial will discuss how to get a PHP class name with class name resolution, PHP __CLASS__ constant, and the get_class() method. You will learn its usage for the class name resolution in and out of a class.
Use Class Name Resolution to Get Class Name in PHP
You can get a class name via class name resolution when you have a namespace in your code. The result is a Fully Qualified Class Name (FQCN).
This feature is available in PHP as ClassName::class . It is useful when you have a namespace in your PHP.
In the following code example, the class name resolution via ClassName::class will return the class name of the associated class:
php namespace YourNameSpace; // Define a class class HelloClassName <> // Get the class name from ::class echo HelloClassName::class; ?>
YourNameSpace\HelloClassName
If you want to use this feature in a class method, you can get the class name via the static method. You’ll write this as static::class .
The next code example shows how to get a class name in a class method.
php namespace YourNameSpace; // Define the class name class HelloClassName /** * Define a function that returns * the class name via static::class */ public function getClassName() return static::class; > > // Create a new object $hello_class_name = new HelloClassName(); // Get the class name echo $hello_class_name->getClassName(); ?>
YourNameSpace\HelloClassName
Use __CLASS__ Constant to Get Class Name in PHP
The __CLASS__ constant is part of the PHP predefined constant. You can use it within a class to get a class name.
The following code will get the class name via the __CLASS__ constant.
php // Define the class class Hello // This function will return the // class name function HelloName () return __CLASS__; > > // Create a new object $hello_object= new Hello(); // Get the class name echo $hello_object->HelloName(); ?>
Use get_class() Function to Get Class Name in PHP
PHP provides a get_class() function. This function will return the class name. You can use it in procedural and object-oriented programming. First, we’ll take a look at the procedural style.
The next code block defines a class with a single function. The function within the class will return the class name when its argument is the this keyword.
To get the class name, you create an object from the class; then, you pass the object’s name to get_class() .
php // Define a class class Hello function class_name() echo "The class name is: ", get_class($this); > > // Create a new object $new_hello_object = new Hello(); // Get the class name $new_hello_object->class_name(); // Also, you can get the class name // via an external call // echo get_class($new_hello_object); ?>
At first, for the OOP style, you can return the get_class() function from a static class.
php // Define a class class Hello public static function class_name() return get_class(); > > // Get the class name $class_name = Hello::class_name(); echo $class_name; ?>
This method has its limitations because when you extend the class, the extended class will return the name of the parent class and not the extended class. To solve this, you can use get_called_class() .
The get_called class() function relies on Late Static Binding. With this function, PHP will return the name of the calling class. It solves the situation where the extended class returns the name of its parent class rather than its own.
php // Define a class class Hello // A static function that returns the // name of the class that calls it public static function called_class_name() return get_called_class(); > // This function will return the // defining class name public static function get_defining_class() return get_class(); > > class ExtendHello extends Hello > $hello_class_name = Hello::called_class_name(); $extended_class_name = ExtendHello::called_class_name(); $extend_hello_parent_class = ExtendHello::get_defining_class(); echo "Hello class name: " . $hello_class_name . "\n"; echo "Extended Hello class name: " . $extended_class_name . "\n"; echo "Extended Hello parent class name: " . $extend_hello_parent_class . "\n"; ?>
Hello class name: Hello Extended Hello class name: ExtendHello Extended Hello parent class name: Hello
Use Reflection Class to Get Class Name in PHP
Reflection Class is a concise way to get a class name in PHP. You create a class; within this class, create a function that returns a new Reflection class.
The Reflection class should have its argument set to $this . Afterward, you can get the class name via the getShortName() method available with the Reflection class.
php // Define a class class Hello // A function that returns the class // name via reflection public function HelloClassName() return (new \ReflectionClass($this))->getShortName(); > > // Create a new class name $hello_class_name = new Hello(); // Get the class name echo $hello_class_name->HelloClassName(); ?>
Use ::class on Object to Get Class Name in PHP
The ::class feature worked on classes before PHP 8. Since PHP, when you create an object from a class, you can get the class name from the created object with ::class .
You’ll find an example in the following code block.
php namespace YourNameSpace; // define the class class HelloClassName > // Create a new object $hello_class_name = new HelloClassName(); // Get the class name from the object // via ::class echo $hello_class_name::class; ?>
YourNameSpace\HelloClassName
Habdul Hazeez is a technical writer with amazing research skills. He can connect the dots, and make sense of data that are scattered across different media.