php 7 — PHP переопределить слабое приведение типа возвращаемого значения функции

Согласно документации 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);
}
}

1

Решение

Это невозможно так как это значение на уровне языка во время компиляции.

Единственное, что вы можете сделать, это переопределить родительский тип возврата:

public function getResponse(): []  // though parent has "Reponse" type
{
return [];
}
0

Другие решения

Я написал свою собственную реализацию, чтобы сделать это на PHP, так как ни одна не существовала. Вот как это работает.

Это две базовые функции.


  1. 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
    );
    

  1. 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'
    );
    

Оба эти метода могут использоваться для принудительного выполнения функций строгого возвращаемого типа, которые принимают несколько возвращаемых типов, которые могут быть приведены к возвращаемому типу в реализации для каждого класса.

0

По вопросам рекламы [email protected]