#7.16 php ООП Анонимные классы и функции, замыкания

Анонимные функции

Анонимные функции в PHP — это функции, не имеющие определенного имени:

function($param)
{
    ...
}

Такие выражения PHP автоматически преобразует в объекты встроенного класса Closure.

Анонимные функции можно присваивать переменным:

<?php
$f = function($text) 
{ 
    echo $text;
};

$f("Hello, world!"); 

Или передавать в качестве параметра другой функции:

<?php
$arr = [1, 2, 3, 4, 5];
$arr2 = array_map(function($x) {
    return $x + 1;
}, $arr);

print_r($arr2); 

Замыкания

В PHP анонимные функции могут запоминать состояние переменных из своего окружения на момент создания (такие функции в программировании называются замыканиями). Все переменные окружения, которые должны войти в замыкание, перечисляются в скобках после ключевого слова use

<?php
$text = "Привет, мир!";

$example = function() use ($text) 
{
    echo $text;
};

$text = "Hello, world!";
$example(); // "Привет, мир!"

Анонимные классы

По аналогии с анонимными функциями, в PHP можно создавать анонимные классы.

new class() 
{
    ...
}

Это позволяет создавать простые одноразовые объекты "на лету".

<?php
print_r(new class("Hello, world!") {
    public $text;
    
    public function __construct($text)
    {
        $this->text = $text;
    }

});

Результат:
class@anonymous Object ( [text] => Hello, world! )

Если объект анонимного класса является возвращаемым значением некоторой функции:

function f()
{
    return new class() {};
}

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

Анонимные классы могут наследовать другие классы. Если анонимный класс определяется в другом классе, то для доступа к защищённым свойствам и методам внешнего класса, используется наследование. Для доступа из анонимного класса к private-свойствам внешнего класса, они должны быть переданы в конструктор.

<?php
class Outer
{
    private $a = 10;
    protected $b = 4;

    public function f() 
    {
        return new class($this->a) extends Outer{
            private $a;
            public function __construct($a)
            {
                $this->a = $a;
            }
  
            public function f2()
            {
                return $this->a + $this->b;
            }
        };
    }
}

echo (new Outer)->f()->f2(); //14