Могу ли я разрешить два разных типа, используя подсказки типа? Например. Параметр 1 может быть либо из двух классов
function log (User|File $requester) {
}
Могу ли я разрешить два разных типа, используя подсказки типа? Например. Параметр 1 может быть либо из двух классов
function log (User|File $requester) {
}
Академически это называется союзом типов.
Вы можете обманывать, создавая интерфейсы, родительские типы и т.д., Как упоминалось в других ответах, но какой смысл, кроме добавления сложности и LoC в ваш проект? Кроме того, это не может работать для скалярных типов, так как вы не можете расширить/реализовать скалярный тип.
Вместо того, чтобы сделать код более читабельным, вы получите обратное. За исключением случаев, когда эти классы/интерфейсы уже существуют, и они находятся здесь из-за ООП, а не для решения проблемы хинтинга типов.
Канонический ответ в PHP... ну, просто не ставьте подсказку типа. Считалось, что язык не имеет сложной и мощной системы типов, и попытка обойти недостатки языка не является хорошим ответом.
Вместо этого, документируйте свою функцию правильно:
/**
* Description of what the function does.
*
* @param User|File $multiTypeArgument Description of the argument.
*
* @return string[] Description of the function return value.
*/
function myFunction($multiTypeArgument)
{
Это как минимум обеспечит поддержку IDE для автозаполнения и статического анализа кода. Достаточно хорошо при работе над частным проектом, сайтом и т.д.
При разработке общедоступного API (библиотеки PHP и т.д.) Иногда вам может потребоваться быть более осторожным в отношении входных данных пользователей API.
Тогда ответ @tilz0R - это путь:
function log($message) {
if (!is_string($message) && !$message instanceof Message) {
throw new \InvalidArgumentException('$message must be a string or a Message object.');
}
// code ...
}
14 февраля 2015 года было предложено объединение типов PHP RFC для PHP 7.1. После обсуждения и голосования было отклонено 18 "нет" против 11 "да".
Если бы RFC был принят, в PHP были бы типы объединения в точности так, как вы показали (User|File
).
RFC имел некоторые недостатки, но главная причина, по которой он был отклонен, заключается в том, что избиратели, поддерживающие поддержку, весьма сопротивляются изменениям, особенно когда речь идет о строгости типов и других парадигмах программирования (например, "зачем нам нужны объединения типов, когда по умолчанию все типы значений "и", что не хорошо для производительности ").
В настоящее время это невозможно в PHP. Однако вы можете иметь interface
и реализовать его для User
и File
, а затем использовать этот интерфейс в качестве подсказки типа в log()
:
<?php
interface UserFile {
}
class User implements UserFile {
}
class File implements UserFile {
}
// snip
public function log (UserFile $requester) {
}
Вы можете проверить внутреннюю функцию типа.
function log ($requester) {
if ($requester instanceof User || $requester instanceof File) {
//Do your job
}
}
Вы можете создать родительский класс для этих двух:
abstract class Parent_class {}
class User extends Parent_class {
// ...
}
class File extends Parent_class {
// ...
}
И используйте его в функции
function log (Parent_class $requester) {
// ... code
}
Или вы можете иметь 2 метода для каждого и один динамический метод:
function logUser($requester)
{
//
}
function logFile($requester)
{
//
}
И динамический
function log($requester)
{
if ($requester instanceof File) {
return $this->logFile($requester);
}
if ($requester instanceof User) {
return $this->logUser($requester);
}
throw new LogMethodException();
}