PHP使用匿名函数

时间:2017-10-29 12:14:17

标签: php php-7 solid-principles

所以我对PHP中的匿名函数感到困惑,我想知道匿名函数是否主要用作品味或编码风格。

我问这个是因为你可以在没有回调函数和更少代码的情况下获得相同的结果。

所以这里有一些测试代码:

$output = 10;
$people = (new People(new John));

 //VERSION 1 ANONYMOUS FUNCTION
$people->run(function ($value) use(&$output){
    $output = $output + $value;
});

var_dump($output); //RESULT => 20

 //VERSION 2 WITHOUT ANONYMOUS FUNCTION
var_dump($people->run() + $output); //RESULT => 30
  

您可以在此处运行并查看完整代码:   https://www.tehplayground.com/IhWJJU0jbNnzuird

<?php

interface HumanInterface
{
    public function hello();
}

class People
{
    protected $person;
    protected $value;

    public function __construct(HumanInterface $person)
    {
        $this->person = $person;
        return $this;
    }

    public function run(callable $callback = null, $name = null)
    {
        $this->value = 10;
        if(is_callable($callback)) {
            return call_user_func($callback, $this->value);
        }

        return $this->value;
    }
}

class John implements HumanInterface
{
    public function hello()
    {
        return 'hi i am john';
    }
}
$output = 10;
$people = (new People(new John));
$people->run(function ($value) use(&$output){
    $output = $output + $value;
});

var_dump($output);
var_dump($people->run() + $output);
  

所以我的问题是:为什么要使用匿名函数?这是一个问题   个人选择?

2 个答案:

答案 0 :(得分:1)

如果匿名函数或“闭包”用作一次性回调,则非常有用。例如,如果您使用PHP的usort方法。第二个参数可以是Closure。因此,不是编写一次使用的命名函数,而是再次使用Closure。 恕我直言,这是使用闭包的唯一方法:作为回调。

答案 1 :(得分:1)

匿名函数可用于传递以供稍后执行或其他代码接受函数。使用它们可以大大减少执行操作所需的代码。

想象一下,你有一个UserCollection对象使用下面的泛型Collection。您希望将UserCollection简化为仅限某个国家/地区的用户。因此,您可以在findByCountry()上添加方法UserCollection

public function findByCountry($country) : UserCollection {
    $subset = new UserCollection;
    foreach ($this->users as $user) {
        if ($user->country === $country) {
            $subset->add($user);
        }
    }
    return $subset;
}

这一切都很好,但是额外的finder方法都会做同样的事情:迭代并收集到只有标准不同的子集。所以很多样板代码。

您可以通过在基础Collection上添加方法find(callable $callback)轻松地将样板与标准分开,如下所示:

public function find(callable $criteria) : Collection {
    $subset = new Collection;
    foreach ($this->users as $user) {
        if ($criteria($user)) {
            $subset->add($user);
        }
    }
    return $subset;
}

这是一个通用的查找器。现在,UserCollection中的代码只包含实际条件:

public function findByCountry($country): UserCollection {
    return $this->subset(function(User $user) {
        return $user->country === $country;
    });
}

private function subset($criteria): UserCollection {
    return new UserCollection($this->allUsers->find($criteria));
}

通过将标准与样板分开,可以更容易地掌握您尝试按国家/地区查找用户的信息。没有迭代代码会分散实际标准的注意力。因此,理解起来更容易,写作也更省力。此外,您不会意外地弄乱迭代,因为它在其他地方定义。

使用这样的匿名函数时,它们与使用策略模式或FilterIterator非常相似。值得注意的是,您正在动态创建它们。

请注意,您必须differentiate between Lambdas and Closures。我故意忽略了这个答案的区别。