Есть ли функция массива для вызова?

Параметр

Внутри SomeClass есть f2member, принимающий два целочисленных аргумента и производящий их сумму. Тест проходит, показывая, что вызов действительно работает, и возвращает ожидаемый результат. Который вызывает $g с двумя параметрами 1 и 1, возвращая 2.

Важно: это работает только для php 5.4.11 и выше проверка совместимости

class SomeClass extends PHPUnit_Framework_TestCase
{   
    function f2member($a,$b)
    {
        return $a + $b;
    }

    /**
     * @test
     */
    public function test()
    {
        $g = array($this,'f2member');
        $this->assertEquals(2, $g(1,1)); // squiggle line under $g
    }
}

Проблема

Однако это выдает предупреждение внутри phpStorm при каждом вызове метода и волнистую линию под $g:

предупреждение о волнистой линии в phpStorm

Имя функции должно быть вызываемым — строка, Closure или класс, реализующий __invoke, текущий массив

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

Пытаться

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

/**
 * @param array $arr
 *
 * @return callable
 */
function callable_for($arr)
{
    return $arr;
}

Это возвращает массив, но также явно сообщает системе типов, что получается из функции callable_for. С этой аннотацией типа phpStorm теперь перестает жаловаться на это предупреждение, хотя по-прежнему возвращает массив.

$g = callable_for(array($this,'f2member'));

Вопрос

Разве нет чего-то готового, например, моего callable_for в php для достижения этого? Если ответ отрицательный, то я ищу самое краткое решение, которое мы можем найти.

Я уже пробовал искать на SO, php.net и в Google. Возможно, я просто искал неправильные словосочетания, вот только два примера:

  • массив для вызываемого php
  • создать дескриптор вызываемого метода php

Большая фотография

На случай, если возникнут подозрения, это X/Y-проблема: у меня есть другая функция, принимающая вызываемый объект в качестве параметра. С замыканиями очень естественно определить что-то, что может быть вызвано позже. Однако как мне определить вызываемый объект для члена или статического метода, не заключая его в другое закрытие делегирования? Обозначение массива позволяет использовать его для унифицированной передачи: замыканий или дескрипторов статических/членных методов в мою более позднюю функцию. Сейчас я пытаюсь найти краткое решение, близкое к этому.


person isaias-b    schedule 05.01.2016    source источник


Ответы (2)


Таким образом, еще одним усовершенствованием может быть модификация callable_for, чтобы она принимала два аргумента и переносила обе обязанности; для создания массива и документирования целевого типа возвращаемого значения.

/**
 * @param mixed $context
 * @param string $method
 *
 * @return callable
 */
function callable_for($context, $method)
{
    return array($context, $method);
}

Использование этой реализации повышает краткость объявления $g до приемлемого уровня.

$g = callable_for($this,'f2member');

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

person isaias-b    schedule 05.01.2016
comment
это возвращает массив, а не вызываемый. - person I wrestled a bear once.; 06.01.2016
comment
@Pamblam Я обновил вопрос, чтобы отразить, что я знаю, что это возвращает массив, но также добавил мотивацию для этой неуклюжей настройки. - person isaias-b; 06.01.2016
comment
я удалил свой ответ, очевидно, я не понял ваш вопрос, но в ответ на ваш другой комментарий, я хотел бы увидеть, как вы можете вызвать массив, если вы будете так любезны, чтобы опубликовать пример этого.. - person I wrestled a bear once.; 06.01.2016
comment
@Pamblam Никто не идеален, просто запустите phpunit на указанном в вопросе тесте phpunit. Массив в этом присваивании $g = array($this, 'f2member'); будет преобразован во что-то, чему можно передать список аргументов, при вызове $g(1,1) он должен оцениваться как и ожидалось. Затем это вернет 2 и пропустит утверждение в тестовом примере. Или просто нажмите эту ссылку. Однако из связанного ответа справа я получил информацию о том, что этот стиль может быть обескуражен. - person isaias-b; 06.01.2016
comment
вау, это очень круто, спасибо, что поделились.. извините, что сомневаюсь в вас :p однако, если вы посмотрите на свой 3v4l, он покажет ту же ошибку для php ‹5.4. похоже, проблема связана с версией PHP, которую вы используете. - person I wrestled a bear once.; 06.01.2016
comment
Я уже добавил информацию к вопросу, чтобы уменьшить путаницу. Я уже знал о нарушении совместимости в этой версии, но теперь вы также заставили меня задуматься об этом с новой точки зрения. Может быть, моя среда выполнения php в phpStorm использует более старую версию для проверки кода? Я не смог найти конфигурацию для него при быстром запуске, я проверю, если это завтра. Это может быть причиной предупреждения. Хотя я должен был получить сообщение об ошибке, но я определенно получил предупреждение. - person isaias-b; 06.01.2016

Вопрос был задан четыре года назад, но после некоторых исследований я нашел метод Closure::fromCallable: https://www.php.net/manual/de/closure.fromcallable.php

person René Pardon    schedule 21.01.2020