PHP コア機能の匿名関数

藏色散人
リリース: 2023-04-07 18:22:01
転載
2775 人が閲覧しました

提案された

匿名関数が出現する前は、すべての関数は使用する前に名前を付ける必要がありました

function increment($value)
{
    return $value + 1;
}
array_map('increment', [1, 2, 3]);
ログイン後にコピー

関数を使用するだけで済む場合もあります匿名関数を使用すると、コードがより簡潔かつ直感的になり、関数が他の場所で使用されるのを防ぐこともできます

array_map(function($value){
    return $value + 1;
}, [1, 2, 3]);
ログイン後にコピー

定義と使用

PHP はクロージャと匿名を扱います関数は同等の概念 (この記事では総称して匿名関数と呼びます) であり、本質的には関数に見せかけたオブジェクトです。

匿名関数の本質はオブジェクトであるため、オブジェクトと同じように、匿名関数も変数に割り当てることができます

$greet = function(string $name){
    echo "hello {$name}";
}
$greet("jack") // hello jack
ログイン後にコピー

すべての匿名関数はクロージャ オブジェクトのインスタンスです

$greet instanceof Closure // true
ログイン後にコピー

オブジェクトには親スコープがないため、使用する変数を手動で宣言するには use を使用する必要があります。

$num = 1;
$func = function() use($num){
    $num = $num + 1;
    echo $num;
}
$func();  // 2
echo $num;  // 还是 1
ログイン後にコピー

無名関数内の変数を有効にしたい場合は、参照渡しを使用する必要があります。 -value

$num = 1;
$func = function() use(&$num){
    $num = $num + 1;
    echo $num;
}
$func();  // 2
echo $num;  // 2
ログイン後にコピー

PHP 5.4 以降、クラスで匿名関数を使用する場合、匿名関数の $this は現在のクラスに自動的にバインドされます

class Foo {
    public function bar()
    {   
        return function() {
            return $this;
        };
    }
}
$foo = new Foo();
$obj = $foo->bar(); // Closure()
$obj();   // Foo
ログイン後にコピー

自動バインディングを有効にするには、静的匿名関数を使用できます

class Foo {
    public function bar()
    {   
        return static function() {
            return $this;
        };
    }
}
$foo = new Foo();
$obj = $foo->bar(); // Closure()
$obj();   // Using $this when not in object context
ログイン後にコピー

匿名関数の本質

匿名関数の本質は、次のような Closure オブジェクトです。 5 つのメソッド

Closure {
    private __construct ( void )
    public static bind ( Closure $closure , object $newthis [, mixed $newscope = "static" ] ) : Closure
    public bindTo ( object $newthis [, mixed $newscope = "static" ] ) : Closure
    public call ( object $newthis [, mixed $... ] ) : mixed
    public static fromCallable ( callable $callable ) : Closure
}
ログイン後にコピー

__construct - 匿名関数のインスタンス化を防止します

$closure = new \Closure();
// PHP Error:  Instantiation of 'Closure' is not allowed
ログイン後にコピー

Closure::bindTo - 現在の匿名関数オブジェクトをコピーし、指定された $this オブジェクトとクラス スコープをバインドします。平たく言えば、匿名関数を指定したオブジェクトに手動でバインドすることを意味し、これを使用してオブジェクトの機能を拡張できます。

// 定义商品类
class Good {
    private $price;
    public function __construct(float $price)
    {
        $this->price = $price;
    }
}
// 定义一个匿名函数,计算商品的促销价
$addDiscount = function(float $discount = 0.8){
    return $this->price * $discount;
}
$good = new Good(100);
// 将匿名函数绑定到 $good 实例,同时指定作用域为 Good
$count = $addDiscount->bindTo($good, Good::class); 
$count(); // 80
// 将匿名函数绑定到 $good 实例,但是不指定作用域,将无法访问 $good 的私有属性
$count = $addDiscount->bindTo($good); 
$count(); // 报错
ログイン後にコピー

Closure::bind - 2 つの使用法がある、bindTo メソッドの静的バージョン:

使用法 1:bindTo メソッドと同じ効果を実現するため

$count = \Closure::bind($addDiscount, $good, Good::class);
ログイン後にコピー

使用法 2: 匿名関数を (オブジェクトではなく) クラスにバインドします。2 番目のパラメーターを null

// 商品库存为 10
class Good {
    static $num = 10;
}
// 每次销售后返回当前库存
$sell = static function() {
    return"当前库存为". --static::$num ;
};
// 将静态匿名函数绑定到 Good 类中
$sold = \Closure::bind($sell, null, Good::class);
$sold(); // 当前库存为 9
$sold(); // 当前库存为 8
ログイン後にコピー

call に設定することを忘れないでください - PHP 7 New call メソッドは匿名関数をバインドして呼び出すことができます。構文が単純になるだけでなく、パフォーマンスも向上します。

// call 版本
$addDiscount->call($good, 0.5);  // 绑定并传入参数 0.5,结果为 50
// bindTo 版本
$count = $addDiscount->bindTo($good, Good::class, 0.5); 
$count(); // 50
ログイン後にコピー

fromCallable - 指定された呼び出し可能関数を匿名関数に変換します

class Good {
    private $price;
    public function __construct(float $price)
    {
        $this->price = $price;
    }
}
function addDiscount(float $discount = 0.8){
    return $this->price * $discount;
}
$closure = \Closure::fromCallable('addDiscount');
$good = new Good(100);
$count = $closure->bindTo($good);  
$count = $closure->bindTo($good, Good::class);   // 报错,不能重复绑定作用域
$count(); // 报错,无法访问私有属性
ログイン後にコピー

fromCallable は

$reflexion = new ReflectionFunction('addDiscount');
$closure = $reflexion->getClosure();
ログイン後にコピー

と同等です。ここで特別な注意が必要な点は、bindTo を使用する場合、2 番目のパラメータがバインディングを指定している場合、それが fromCallable から変換されたクロージャであるか、リフレクションを使用して取得されたクロージャであるかということです。クラスの場合、エラーが報告されます

Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()
ログイン後にコピー

以上がPHP コア機能の匿名関数の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
php
ソース:learnku.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート