ホームページ  >  記事  >  バックエンド開発  >  PHP の static キーワードと yield キーワードについての深い理解

PHP の static キーワードと yield キーワードについての深い理解

黄舟
黄舟オリジナル
2017-09-19 09:27:381899ブラウズ

この記事では、主に PHP の static キーワードと yield キーワードに関する関連情報をサンプル コードを通じて詳しく紹介します。この記事は、PHP を学習したり使用したりするのに役立ちます。以下に来て私と一緒に学びましょう。

前書き

この記事では主に、PHP の static キーワードと yield キーワードに関する関連コンテンツを紹介し、参考と学習のために共有します。以下では多くを説明しません。詳しい紹介。

まず静的キーワードについて話しましょう。この記事では、静的メソッドと遅延バインディングの使用についてのみ説明します。

static メソッドの変更にいつ使用されますか?

static キーワードは、メソッドと属性の変更に使用されることが知られています。 では、プロジェクトではどのようなシナリオで使用しますか?

すべてのメソッドが静的である必要があるプロジェクトをいくつか経験しました。もちろん、コントローラー メソッドではこれができません。理由の1つは、静的メソッドの実行効率が高いかどうかです。それでは、これをもとに分析してみましょう。

まず、実行効率が高いことに異論はありません。効率が良いから遠慮なくプロジェクトに使っていいということでしょうか?この問題について議論するために、まずプログラミング言語の歴史を振り返ってみましょう。初期にはオブジェクト指向プログラミングはなく、構造化プログラミングが使用されていました。その後、オブジェクト指向が登場し、インスタンス化の概念が生まれました。

上記の簡単な開発プロセスから、パフォーマンスだけを目的とする場合は、オブジェクト指向開発の必要性がないようであることがわかります。それでは、これらのマスターは、C++ や Java などの言語にオブジェクト指向とインスタンス化を導入することについてどう考えているのでしょうか?それは、開発においてプロジェクトがますます大きくなり、より適切なコードの組織化とプログラミング的思考が必要になるからだと思います。

static を振り返ると、定義されている static メソッドは非常に効率的ですが、メモリを占有し続け、ライフサイクルはプログラムが終了するときにのみ終了し、その間は破棄できないなどの副作用があります。もう 1 つは設計パターンによるもので、一般に結合が強く、静的属性は外部から変更できます。第 3 に、静的に定義されたメソッドはオーバーライドによって書き換えることができません。第 4 に、ioc di などの概念は役に立ちません。単体テストを実行する場合、メソッドは頭の痛い問題です。

上記のことから、将来的には静的メソッドの使用をやめ、インスタンス化してメソッドを正直に呼び出すだけでよいような気がしますか?私たちは合理的でなければなりませんが、極端すぎてどこでも使用することはできませんし、まったく使用できないこともあります。結論: オブジェクト指向の考え方を学びましょう。コードを書くときに最初に考慮するのは、拡張性 (ビジネスの急速な変化に対処する) と保守性 (オンラインの問題をタイムリーに修復する) だと思います。高効率は最後に検討する必要があります (効率を最適化する方法はたくさんあるため、すべてのメソッドに static を追加する必要はありません)。オブジェクト指向の観点から、このメソッドが完全に独立しており、クラス属性とは何の関係もない場合は、static を使用します。

つまり、効率のためにコードの美しさを壊すのではなく、オブジェクト指向の観点とソフトウェア設計のレベルから構文の使用を検討します。

static Late static binding

これはPHPのドキュメントで詳しく紹介されていますが、私はこれまでほとんどこの場所に注目したことがありませんでした。

遅延バインディングは、ある程度静的メソッドのオーバーロードに似ていると思います。これを説明するための PHP ドキュメントの例を次に示します


<?php
class A {
 public static function who() {
 echo __CLASS__;
 }
 public static function test() {
 self::who();
 static::who();// 后期静态绑定
 }
}

class B extends A {
 public static function who() {
 echo __CLASS__;
 }
}

B::test();

self::who() が呼び出されると、次の出力が行われます: A. static::who() が B を出力する場合self::who() 调用,会输出:A。如果是 static::who() 会输出 B

这样来看,是不是相当于 class B重写了父类 A 的 who()

このように見ると、クラス B が親クラス A の who() メソッドをオーバーライドするのと同じでしょうか?したがって、この機能を柔軟に使用すると、静的をより柔軟にすることができます。パフォーマンスの利点を最大限に活用し、拡張性の低さの問題を解決します。もちろん、オブジェクト指向の観点からは、すべてが適度に行われることは変わりません。

PHPにおけるyieldの使用シナリオ

正直に言うと、私はPHPにこのような構文があることを長い間知りませんでした。ある日、js でこのキーワードに出会うまで、なぜこのキーワードが世界最高の言語で利用できないのか、疑問に思っていました。ドキュメントを振り返ると、これがまさに世界で最高の言語であることがわかります。

それでは、収量の使用シナリオは何でしょうか?つい最近、SG の誰かが私にそれを解決するように頼んだんです。皆さんももっと自分のビジネスと合わせて活用していただければと思います。 yield と Iterator の間には比較はありません。読んでいただければどちらの方が簡潔か分かると思います。 🎜

先说它的使用场景,还是得先回顾历史,在没有 yield 之前,我们要生成一个数组,只能一次性把所有内容全部读入内存(当然也可以通过实现 Iterator接口实现一个迭代)。有了 yield 之后,我们可以通过一个简单的 yield 关键字,完成一个数组的生成,并且是用到的时候才会产生值,相对而言内存占用肯定会下降。空口无凭,咱们下面通过代码实际检验一下上面的结论。

先来看普通模式


<?php

function generateData($max)
{
 $arr = [];
 for ($i = 0; $i <= $max; $i++) {
 $arr[] = $i;
 }
}

echo &#39;开始前内存占用:&#39; . memory_get_usage() . PHP_EOL;
$data = generateData(100000);
echo &#39;生成完数组后内存占用:&#39; . memory_get_usage() . PHP_EOL;
unset($data);
echo &#39;释放后的内存占用:&#39; . memory_get_usage() . PHP_EOL;

运行得到结果:


开始前内存占用:231528
生成完数组后内存占用:231712
释放后的内存占用:231576

前后的差值是:184

使用yield后的效果


function generateData($max)
{
 for ($i = 0; $i <= $max; $i++) {
 yield $i;
 }
}

echo &#39;开始前内存占用:&#39; . memory_get_usage() . PHP_EOL;
$data = generateData(100000);// 这里实际上得到的是一个迭代器
echo &#39;生成完数组后内存占用:&#39; . memory_get_usage() . PHP_EOL;
unset($data);
echo &#39;释放后的内存占用:&#39; . memory_get_usage() . PHP_EOL;

运行结果:


开始前内存占用:228968
生成完数组后内存占用:229824
释放后的内存占用:229016

前后的差值是:856

奇怪,使用了 yield 后,内存占用反而上升了,这是什么鬼?别急。上面我们参数传入的是 1,000,00,我现在将传入参数改成改成 1,000,000试试。

第一个方法得到的结果是:


开始前内存占用:231528

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 32 bytes) in /test/yield.php on line 6

看了吧,一百万次的循环时,一次性载入内存,超出了限制。那么再来看 yield 的执行结果:


开始前内存占用:228968
生成完数组后内存占用:229824
释放后的内存占用:229016

前后的差值依然是:856

好了到这里,应该看出来了,yield无论数组大小,占用均是 856 ,这是因为它自身,它在你进行迭代的时候才会产生真实数据。

所以如果你的数据来源非常大,那么用 yield 吧。如果数据来源很小,当然选择一次载入内存。

总结

以上がPHP の static キーワードと yield キーワードについての深い理解の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。