Невозможно назначить замыкание в свойстве stdClass в php - PullRequest
0 голосов
/ 28 января 2019

Я пытался написать js-подобный php, используя замыкания.Однако я не понимаю, почему я не могу присвоить замыкание свойству stdClass.

Код объясняет сам себя:

$sum = function ($a, $b) {return $a + $b;};
echo $sum(11, 11);
// prints 22



$arr = [];
$arr['sum'] = function ($a, $b) {return $a + $b;};
echo $arr['sum'](22, 22);
// prints 44



$cl = new stdClass;
$cl->sum = function ($a, $b) {return $a + $b;};
echo $cl->sum(33, 33);
// Fatal error: Uncaught Error: Call to undefined method stdClass::sum()



# although I can't think of any use cases for this
class Custom {
    public $sum = NULL;

    function __construc() {
        $this->sum = function ($a, $b) {return $a + $b;};
    }
}

$custom = new Custom;
echo $custom->sum(44, 44);
// Fatal error: Uncaught Error: Call to undefined method Custom::sum()

Ответы [ 2 ]

0 голосов
/ 28 января 2019

Вы можете использовать методы закрытия bind(), bindTo() или call().

$cl = new stdClass;
$sum = function ($a, $b) {return $a + $b;};
Closure::bind($sum, $cl);

echo $sum(33, 33); // this function is now part of the class. 

Если вы хотите расширить эту функциональность, вы можете создать в классе функцию регистра, которая полагается нана магические методы, такие как __call(), чтобы проверить, существует ли этот метод, и если это так, вызвать внутреннее зарегистрированное закрытие.

0 голосов
/ 28 января 2019

Просто оберните имя свойства в круглые скобки.

echo ($cl->sum)(33, 33);
echo ($custom->sum)(44, 44);

Пример из 3v4l:

https://3v4l.org/3ZqNV

Редактировать на основе комментариев:

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

В PHP объект может иметь как свойства, так и метод.

Предположим, чтоу нас есть следующий код:

class MyClass 
{

    public $foo;

    public function __construct() 
    {
        $this->foo = function(int $a, int $b): int {
            return $a * $b;
        };
    }

    public function foo(int $a, int $b): int 
    {
        return $a + $b;
    }
}

$myClass = new MyClass();

echo $myClass->foo(2, 3);

Оба свойства foo и метод foo имеют одинаковую сигнатуру, но какова была воля программиста?

Этот код вызовет метод foo и печатает 5, поэтому любая строка $var->name() интерпретируется как вызов метода.

Если вы хотите вызвать замыкание внутри свойства, вы должны использовать другой синтаксис, чтобы не было двусмысленности.

echo ($myClass->foo)(2, 3) //Prints 6

https://3v4l.org/PXiMQ

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...