Согласно документации PHP по строгой типизации найдено Вот
По умолчанию PHP преобразует значения неправильного типа в ожидаемый скалярный тип, если это возможно. Например, функция, которой присвоено целое число для параметра, который ожидает строку, получит переменную типа string.
Мне любопытно, есть ли способ переопределить эту функцию, чтобы настроить способ, которым выполняется принуждение.
Например
function getResponse() : \Namespace\Response {
return []; // Ideally, this would be coerced into a Response object.
}
. . .
namespace Namespace;
class Response {
public $data;
public function __construct(array $arr)
{
$this->data = $arr;
}
public static function __coerce($value)
{
if (! is_array($value)) {
throw new \TypeError('Wrong type during coercion.');
}
return new self($value);
}
}
Это невозможно так как это значение на уровне языка во время компиляции.
Единственное, что вы можете сделать, это переопределить родительский тип возврата:
public function getResponse(): [] // though parent has "Reponse" type
{
return [];
}
Я написал свою собственную реализацию, чтобы сделать это на PHP, так как ни одна не существовала. Вот как это работает.
Это две базовые функции.
multiReturnFunction
функция. (Используется для вызова глобальных функций и аноновых функций)
/**
* Call a global function and use type coercion
* for non-registered return types.
*
* @param closure $closure The function to execute.
* @param string $returnType The registered return type.
* @param array $params The parameters to pass to the function.
*
* @return mixed The result of the function to execute.
*/
function multiReturnFunction($closure, $returnType, ...$params)
{
$val = $closure(...$params);
if (gettype($val) === 'object') {
if (get_class($val) != $returnType) {
if (method_exists($returnType, '__coerce')) {
$val = $returnType::__coerce($val);
} else {
throw new \Exception(
'Returned value does not match the return type defined, '.
'and no __coerce function is visible.'
);
}
}
} else if (gettype($val) != $returnType) {
if (method_exists($returnType, '__coerce')) {
$val = $returnType::__coerce($val);
} else {
throw new \Exception(
'Returned value does not match the return type defined, '.
'and no __coerce function is visible.'
);
}
}
return $val;
}
multiReturnFunction
функция будет вызывать замыкание и использовать __coerce
функция класса возвращаемого типа для приведения возвращаемого типа, если результирующий возвращаемый тип не совпадает.
Пример из multiReturnFunction
функция
Определите класс, который мы будем использовать, и обязательно дайте ему __coerce
функция.
Замечания:
__coerce
функции принимают единственную переменную для объекта, который мы будем пытаться привести к этому типу класса. Функция должна быть объявлена статической.
class MyClass
{
private $data;
public function __construct(array $value)
{
$this->data = $value;
}
public static function __coerce($value)
{
if (! is_array($value)) {
throw new \Exception(
'Returned value does not match the return type defined.'
);
}
return new self($value);
}
}
Далее вам нужно будет позвонить multiReturnFunction
функция с использованием вашего класса и анонимной функции.
$resultingMyClass = multiReturnFunction (
// Multi return type function.
function($name, $age) {
// Here you can return either a MyClass instance, or an array.
// All other types will throw an exception.
return [$name, $age];
},
// Return Type, any other type will be coerced through this class.
MyClass::class,
// Function parameters.
'Nathan', 23
);
multiReturnMethod
функция. (Используется для вызова методов класса)
/*
* Call a class method and use type coercion
* for non-registered return types.
*
* @param object $obj The object to call the method on.
* @param string $method The method to call on the object.
* @param string $returnType The registered return type.
* @param array $params The parameters to pass to the method.
*
* @return mixed The result of the method to execute.
*/
function multiReturnMethod($obj, $method, $returnType, ...$params)
{
$val = $obj->{$method}(...$params);
if (gettype($val) === 'object') {
if (get_class($val) != $returnType) {
if (method_exists($returnType, '__coerce')) {
$val = $returnType::__coerce($val);
} else {
throw new \Exception(
'Returned value does not match the return type defined, '.
'and no __coerce function is visible.'
);
}
}
} else if (gettype($val) != $returnType) {
if (method_exists($returnType, '__coerce')) {
$val = $returnType::__coerce($val);
} else {
throw new \Exception(
'Returned value does not match the return type defined, '.
'and no __coerce function is visible.'
);
}
}
return $val;
}
multiReturnMethod
функция будет вызывать метод класса и использовать __cooerce
функция класса возвращаемого типа для приведения возвращаемого типа, если результирующий возвращаемый тип не совпадает.
Пример из multiReturnMethod
функция
Примечание: мы будем использовать
MyClass
класс, который мы создали раньше как тип возвращаемого значения.
Определите класс, который мы можем использовать для вызова метода класса.
class MRFClass {
function callMe($name)
{
return [$name, 1, 2, 3];
}
}
Позвоните multiReturnMethod
функция с использованием вашего класса и анонимной функции.
$resultingMyClass = multiReturnMethod (
// The object that we will be calling the
// class method on.
new MRFClass(),
// The class method to call, by name.
'callMe',
// The return type to coerce to.
MyClass::class,
// The function parameters.
'Nathan'
);
Оба эти метода могут использоваться для принудительного выполнения функций строгого возвращаемого типа, которые принимают несколько возвращаемых типов, которые могут быть приведены к возвращаемому типу в реализации для каждого класса.