ホームページ >バックエンド開発 >PHPチュートリアル >PHPの静的メソッドで非静的ステップを呼び出すことはお勧めできません
PHP の静的メソッドが非静的メソッドを呼び出すことはお勧めできません
その日、私はこのトピックに非常に興味があったので、それを説明するために関連情報を調べました。ただ、書いた内容に漏れがあるかどうかわからないので、皆さんに向けてここに投稿させていただきました。間違っている、または不合理な記述を見つけた場合は、お気軽にコメントしてください。もちろん、トマトと卵は受け入れられます。真実は議論の中にのみ存在します。
---------------------------------------
php
での非静的メソッドの静的呼び出し
参考:
1 静的メソッドと非静的メソッド?
http://bytes.com/topic/php/answers/495206-static-method-vs-non-static-method
2 PHP 静的メソッドのパフォーマンス
http://vega.rd.no/articles/php-static-method-performance
PHP は非常に奇妙な言語です。もちろん、CやJavaなどのオブジェクト指向言語を勉強したことがある人向けです。
php
静的メソッドを定義し、className::staticMethod() を通じて呼び出すことができます。もちろん、非静的メソッドは通過します
classObject->nonStaticMethod() が使用されます。これは他の言語にも当てはまりますが、大したことではありません。ただし、使用できます
className::nonStaticMethod() は非静的メソッドを呼び出しますか?この点に関して、Java と C は冷や汗をかくのではないかと思います。実はPHP自体も黒い線だらけです。
なぜそんなことを言うのですか?
まず、オブジェクト指向の静的と非静的について見てみましょう。すべてのオブジェクト指向言語は静的メソッドをサポートしています。静的メソッドはクラスの固定資産に属し、非静的メソッドはクラスに属します。
インスタンスのプライベート プロパティ。メモリ内では、静的メソッドはクラス全体でこのコピーを 1 つだけ保持します。新しいインスタンス オブジェクトをいくつ作成しても、共有されるのはこの 1 つのコピーだけです。非静的なものでは異なりますが、
新しいものをいくつ持っていても、記憶が新しいものを与えてくれるでしょう。また、静的メソッド内では非静的メソッドを呼び出すことはできませんが、静的メソッドは非静的メソッド内で呼び出すことができます。これが静的と非静的の違いです。
オブジェクト指向では、静的を定義するために static キーワードを使用します。静的としてマークされていないメソッドは、クラス名と 2 つのコロンを使用して呼び出すことはできません。 PHP と他のもので大きく異なる点の 1 つは、静的としてマークされていない PHP のメソッドは、クラス名と 2 つのコロンを使用して呼び出すこともできるということです。では、なぜ php にはこのような構文があるのでしょうか?そして、なぜそんなに無力感を感じるのですか?
-----php の無力さに関する以下の話は、関連情報を基に改作され、小説として扱われています-----
php
これほど急速に発展した理由は、そのスピードにあります。 PHP はスクリプト言語として高速性、簡潔性、利便性を追求するため、実行を解釈して処理メソッドを使用することを選択します。その後、国際標準との統合を図るため、対面方式を導入
象のコンセプト。そして、このオブジェクト指向機能が導入されたとき、PHP を驚愕させ、最終的には無力にする何かが起こりました。オブジェクト指向における非常に重要な概念は継承です。継承では、サブクラスの場合、
親クラスのメソッドをオーバーライドし、親クラスの同じ名前のメソッドを呼び出す必要がある場合はどうすればよいですか? php4 バージョンでは、parentClassName::method() というメソッドが提供されます。提案する
このメソッドを使用する場合、知識のある人はすでに問題を発見しています。この呼び出しメソッドはまさに静的メソッドの呼び出しメソッドではないでしょうか。 php4 はすぐに「それは問題ではありません」と答えました。クラス内で使用すると、このメソッドがサブクラスによって調整されていると判断できます。
親クラスのメソッドを使用します。クラス以外で使用すると静的呼び出しと判断されます。必要なのは、そのような呼び出しが検出されたときにメソッド マッピングをクエリすることだけです。実際、考えてみると確かにその通りです。 php4 そこで考えたのが、
呼び出しが正当であるかどうかを確認するためにすべての呼び出しが行われる場合、パフォーマンスにある程度影響します。この問題はプログラマに任せたほうがよいでしょう。プログラマは、クラス内でこの形式の呼び出しのみを使用することを知っています。ああ、神がそうしないのは残念だ
人々の願いを叶えます。 php4 はプログラマーの創造性を過小評価しています。プログラマーはこの方法をすぐに発見し、執拗に使用しました。多くの統合 API もこの風変わりなアプローチを使用し始めています。 php 無力
そしてphp5では、キーワードparentを使用して親クラス関数parent::method()を呼び出す別の方法が導入されました。ただし、php の非静的メソッドを放棄したい場合は、
静的呼び出しは実際には不可能になりました。
------------------
しかし、そうは言っても、この奇妙な PHP の方法に何かメリットがあるのでしょうか?パフォーマンスとメモリ使用量はどうですか?
で
私は、非静的メソッドが定義されていると考え始めました。静的に呼び出す場合、PHP はまずこのメソッドを静的定義に変換し、静的メモリ領域にロードしてから実行します。通常、1つの事業所のみを使用します。
ビジネスクラスのメソッドが非静的に定義され、静的に呼び出される場合、このビジネスクラスのメソッドは 1 つだけメモリにロードされ、静的メソッドのオンデマンドロードが実現されるのではありませんか?ある程度は保存しておいた方が良いのではないでしょうか?
メモリ?パフォーマンスに関しては、静的呼び出しであってもオブジェクト呼び出しであっても、いずれにしろメソッドが実行されるので、パフォーマンスは同じではないでしょうか?また、静的に定義されていないメソッドを静的に呼び出すと、新しいステートメントも節約されます。うーん。それで
そう思っていると、手が書き始めた。
では、現実はどうなのでしょうか?ちょっとしたテストをしてみました。
<p> <span style="color: #000000;"> t</span> <span style="color: #000000;">::</span> <span style="color: #000000;">start();t</span> <span style="color: #000000;">::</span> <span style="color: #008080;">end</span> <span style="color: #000000;">(); </span> <span style="color: #008000;">//</span> <span style="color: #008000;">消除t类首次加载的影响</span> <span style="color: #008000;"> </span> <span style="color: #000000;">t</span> <span style="color: #000000;">::</span> <span style="color: #000000;">start(); model_profile_base</span> <span style="color: #000000;">::</span> <span style="color: #000000;">getBaseInfo(</span> <span style="color: #800080;">$uid</span> <span style="color: #000000;">); t</span> <span style="color: #000000;">::</span> <span style="color: #008080;">end</span> <span style="color: #000000;">(); t</span> <span style="color: #000000;">::</span> <span style="color: #000000;">start(); </span> <span style="color: #800080;">$model</span> <span style="color: #000000;"> </span> <span style="color: #000000;">=</span> <span style="color: #000000;"> </span> <span style="color: #0000ff;">new</span> <span style="color: #000000;"> model_profile_base(); </span> <span style="color: #800080;">$model</span> <span style="color: #000000;">-></span> <span style="color: #000000;">getBaseInfo(</span> <span style="color: #800080;">$uid</span> <span style="color: #000000;">); t</span> <span style="color: #000000;">::</span> <span style="color: #008080;">end</span> <span style="color: #000000;">(); </span> </p>
model_profile_base は、基本的なデータを処理するビジネス クラスであり、比較的複雑であり、プロジェクト内の実際の業務処理に近いものです。
以下は、タイミングおよび統計メモリに使用される t クラスの定義です:
<p> <span style="color: #000000;"> </span> <span style="color: #000000;"><?</span> <span style="color: #000000;">php </span> <span style="color: #0000ff;">function</span> <span style="color: #000000;"> microtime_float() { </span> <span style="color: #0000ff;">list</span> <span style="color: #000000;">(</span> <span style="color: #800080;">$usec</span> <span style="color: #000000;">,</span> <span style="color: #000000;"> </span> <span style="color: #800080;">$sec</span> <span style="color: #000000;">) </span> <span style="color: #000000;">=</span> <span style="color: #000000;"> </span> <span style="color: #008080;">explode</span> <span style="color: #000000;">(</span> <span style="color: #000000;">"</span> <span style="color: #000000;"> </span> <span style="color: #000000;">"</span> <span style="color: #000000;">,</span> <span style="color: #000000;"> </span> <span style="color: #008080;">microtime</span> <span style="color: #000000;">()); </span> <span style="color: #0000ff;">return</span> <span style="color: #000000;"> ((</span> <span style="color: #0000ff;">float</span> <span style="color: #000000;">)</span> <span style="color: #800080;">$usec</span> <span style="color: #000000;"> </span> <span style="color: #000000;">+</span> <span style="color: #000000;"> (</span> <span style="color: #0000ff;">float</span> <span style="color: #000000;">)</span> <span style="color: #800080;">$sec</span> <span style="color: #000000;">); } </span> <span style="color: #0000ff;">class</span> <span style="color: #000000;"> t{ </span> <span style="color: #0000ff;">static</span> <span style="color: #000000;"> </span> <span style="color: #800080;">$start_time</span> <span style="color: #000000;">; </span> <span style="color: #0000ff;">static</span> <span style="color: #000000;"> </span> <span style="color: #800080;">$end_time</span> <span style="color: #000000;">; </span> <span style="color: #0000ff;">static</span> <span style="color: #000000;"> </span> <span style="color: #800080;">$start_memory</span> <span style="color: #000000;">; </span> <span style="color: #0000ff;">static</span> <span style="color: #000000;"> </span> <span style="color: #800080;">$end_memory</span> <span style="color: #000000;">; </span> <span style="color: #0000ff;">public</span> <span style="color: #000000;"> </span> <span style="color: #0000ff;">static</span> <span style="color: #000000;"> </span> <span style="color: #0000ff;">function</span> <span style="color: #000000;"> start() { self</span> <span style="color: #000000;">::</span> <span style="color: #800080;">$start_memory</span> <span style="color: #000000;"> </span> <span style="color: #000000;">=</span> <span style="color: #000000;"> memory_get_usage(); self</span> <span style="color: #000000;">::</span> <span style="color: #800080;">$start_time</span> <span style="color: #000000;"> </span> <span style="color: #000000;">=</span> <span style="color: #000000;"> microtime_float(); </span> <span style="color: #0000ff;">echo</span> <span style="color: #000000;"> </span> <span style="color: #000000;">'</span> <span style="color: #000000;"><br/>Start @</span> <span style="color: #000000;">'</span> <span style="color: #000000;">.</span> <span style="color: #000000;">self</span> <span style="color: #000000;">::</span> <span style="color: #800080;">$start_time</span> <span style="color: #000000;">.</span> <span style="color: #000000;">'</span> <span style="color: #000000;">(</span> <span style="color: #000000;">'</span> <span style="color: #000000;">.</span> <span style="color: #000000;">self</span> <span style="color: #000000;">::</span> <span style="color: #800080;">$start_memory</span> <span style="color: #000000;">.</span> <span style="color: #000000;">'</span> <span style="color: #000000;">)|-------></span> <span style="color: #000000;">'</span> <span style="color: #000000;">; } </span> <span style="color: #0000ff;">public</span> <span style="color: #000000;"> </span> <span style="color: #0000ff;">static</span> <span style="color: #000000;"> </span> <span style="color: #0000ff;">function</span> <span style="color: #000000;"> </span> <span style="color: #008080;">end</span> <span style="color: #000000;">() { self</span> <span style="color: #000000;">::</span> <span style="color: #800080;">$end_time</span> <span style="color: #000000;"> </span> <span style="color: #000000;">=</span> <span style="color: #000000;"> microtime_float(); self</span> <span style="color: #000000;">::</span> <span style="color: #800080;">$end_memory</span> <span style="color: #000000;"> </span> <span style="color: #000000;">=</span> <span style="color: #000000;"> memory_get_usage(); </span> <span style="color: #0000ff;">echo</span> <span style="color: #000000;"> </span> <span style="color: #000000;">'</span> <span style="color: #000000;">End @</span> <span style="color: #000000;">'</span> <span style="color: #000000;">.</span> <span style="color: #000000;">self</span> <span style="color: #000000;">::</span> <span style="color: #800080;">$end_time</span> <span style="color: #000000;">.</span> <span style="color: #000000;">'</span> <span style="color: #000000;">(</span> <span style="color: #000000;">'</span> <span style="color: #000000;">.</span> <span style="color: #000000;">self</span> <span style="color: #000000;">::</span> <span style="color: #800080;">$end_memory</span> <span style="color: #000000;">.</span> <span style="color: #000000;">'</span> <span style="color: #000000;">) :</span> <span style="color: #000000;">'</span> <span style="color: #000000;">; </span> <span style="color: #0000ff;">echo</span> <span style="color: #000000;"> </span> <span style="color: #000000;">'</span> <span style="color: #000000;">|======= 共耗时:</span> <span style="color: #000000;">'</span> <span style="color: #000000;">.</span> <span style="color: #000000;">(self</span> <span style="color: #000000;">::</span> <span style="color: #800080;">$end_time</span> <span style="color: #000000;">-</span> <span style="color: #000000;">self</span> <span style="color: #000000;">::</span> <span style="color: #800080;">$start_time</span> <span style="color: #000000;">)</span> <span style="color: #000000;">.</span> <span style="color: #000000;">'</span> <span style="color: #000000;">,共用内存:</span> <span style="color: #000000;">'</span> <span style="color: #000000;">.</span> <span style="color: #000000;">(self</span> <span style="color: #000000;">::</span> <span style="color: #800080;">$end_memory</span> <span style="color: #000000;">-</span> <span style="color: #000000;">self</span> <span style="color: #000000;">::</span> <span style="color: #800080;">$start_memory</span> <span style="color: #000000;">); } } </span> </p>
この方法では、一度だけ呼び出され、結果は次のようになります:
<p> <span style="color: #000000;"> Start @</span> <span style="color: #000000;">1287561987.1805</span> <span style="color: #000000;">(</span> <span style="color: #000000;">1008368</span> <span style="color: #000000;">)</span> <span style="color: #000000;">|-------></span> <span style="color: #008080;">End</span> <span style="color: #000000;"> @</span> <span style="color: #000000;">1287561987.1806</span> <span style="color: #000000;">(</span> <span style="color: #000000;">1008368</span> <span style="color: #000000;">) </span> <span style="color: #000000;">:|=======</span> <span style="color: #000000;"> 共耗时:</span> <span style="color: #000000;">3.2901763916016E-5</span> <span style="color: #000000;">,共用内存:</span> <span style="color: #000000;">0</span> <span style="color: #000000;"> Start @</span> <span style="color: #000000;">1287561987.1806</span> <span style="color: #000000;">(</span> <span style="color: #000000;">1008368</span> <span style="color: #000000;">)</span> <span style="color: #000000;">|-------></span> <span style="color: #008080;">End</span> <span style="color: #000000;"> @</span> <span style="color: #000000;">1287561987.1938</span> <span style="color: #000000;">(</span> <span style="color: #000000;">1586452</span> <span style="color: #000000;">) </span> <span style="color: #000000;">:|=======</span> <span style="color: #000000;"> 共耗时:</span> <span style="color: #000000;">0.013248920440674</span> <span style="color: #000000;">,共用内存:</span> <span style="color: #000000;">578084</span> <span style="color: #000000;"> Start @</span> <span style="color: #000000;">1287561987.1938</span> <span style="color: #000000;">(</span> <span style="color: #000000;">1586452</span> <span style="color: #000000;">)</span> <span style="color: #000000;">|-------></span> <span style="color: #008080;">End</span> <span style="color: #000000;"> @</span> <span style="color: #000000;">1287561987.1945</span> <span style="color: #000000;">(</span> <span style="color: #000000;">1586652</span> <span style="color: #000000;">) </span> <span style="color: #000000;">:|=======</span> <span style="color: #000000;"> 共耗时:</span> <span style="color: #000000;">0.00065183639526367</span> <span style="color: #000000;">,共用内存:</span> <span style="color: #000000;">200</span> <span style="color: #000000;"> </span> </p>
2 行目は非静的メソッドへの静的呼び出しで、3 行目は非静的メソッドへの通常の呼び出しです。そして、自分の推論が悲劇的なものであることに気づきました。ページを数回更新しましたが、統計結果の大きさはほぼ同じでした。非静的メソッドの静的呼び出しは、メモリ使用量とパフォーマンスの点で満足できるものではありません。結果は少し驚くべきものです。
次に、ループを複数回実行した結果を試します:
<p> <span style="color: #000000;"> t</span> <span style="color: #000000;">::</span> <span style="color: #000000;">start();t</span> <span style="color: #000000;">::</span> <span style="color: #008080;">end</span> <span style="color: #000000;">(); </span> <span style="color: #008000;">//</span> <span style="color: #008000;">消除t类首次加载的影响</span> <span style="color: #008000;"> </span> <span style="color: #000000;">t</span> <span style="color: #000000;">::</span> <span style="color: #000000;">start(); </span> <span style="color: #0000ff;">for</span> <span style="color: #000000;">(</span> <span style="color: #800080;">$i</span> <span style="color: #000000;">=</span> <span style="color: #000000;">0</span> <span style="color: #000000;">; </span> <span style="color: #800080;">$i</span> <span style="color: #000000;"><</span> <span style="color: #000000;">1000</span> <span style="color: #000000;">;</span> <span style="color: #000000;">++</span> <span style="color: #800080;">$i</span> <span style="color: #000000;">) model_profile_base</span> <span style="color: #000000;">::</span> <span style="color: #000000;">getBaseInfo(</span> <span style="color: #800080;">$uid</span> <span style="color: #000000;">); t</span> <span style="color: #000000;">::</span> <span style="color: #008080;">end</span> <span style="color: #000000;">(); t</span> <span style="color: #000000;">::</span> <span style="color: #000000;">start(); </span> <span style="color: #800080;">$model</span> <span style="color: #000000;"> </span> <span style="color: #000000;">=</span> <span style="color: #000000;"> </span> <span style="color: #0000ff;">new</span> <span style="color: #000000;"> model_profile_base(); </span> <span style="color: #0000ff;">for</span> <span style="color: #000000;">(</span> <span style="color: #800080;">$i</span> <span style="color: #000000;">=</span> <span style="color: #000000;">0</span> <span style="color: #000000;">; </span> <span style="color: #800080;">$i</span> <span style="color: #000000;"><</span> <span style="color: #000000;">1000</span> <span style="color: #000000;">;</span> <span style="color: #000000;">++</span> <span style="color: #800080;">$i</span> <span style="color: #000000;">) </span> <span style="color: #800080;">$model</span> <span style="color: #000000;">-></span> <span style="color: #000000;">getBaseInfo(</span> <span style="color: #800080;">$uid</span> <span style="color: #000000;">); t</span> <span style="color: #000000;">::</span> <span style="color: #008080;">end</span> <span style="color: #000000;">(); </span> </p>
その後、さらに言葉にならない結果が出ました:
<p> <span style="color: #000000;"> Start @</span> <span style="color: #000000;">1287562243.5799</span> <span style="color: #000000;">(</span> <span style="color: #000000;">1009372</span> <span style="color: #000000;">)</span> <span style="color: #000000;">|-------></span> <span style="color: #008080;">End</span> <span style="color: #000000;"> @</span> <span style="color: #000000;">1287562243.5799</span> <span style="color: #000000;">(</span> <span style="color: #000000;">1009372</span> <span style="color: #000000;">) </span> <span style="color: #000000;">:|=======</span> <span style="color: #000000;"> 共耗时:</span> <span style="color: #000000;">3.0040740966797E-5</span> <span style="color: #000000;">,共用内存:</span> <span style="color: #000000;">0</span> <span style="color: #000000;"> Start @</span> <span style="color: #000000;">1287562243.58</span> <span style="color: #000000;">(</span> <span style="color: #000000;">1009372</span> <span style="color: #000000;">)</span> <span style="color: #000000;">|-------></span> <span style="color: #008080;">End</span> <span style="color: #000000;"> @</span> <span style="color: #000000;">1287562244.1532</span> <span style="color: #000000;">(</span> <span style="color: #000000;">1587544</span> <span style="color: #000000;">) </span> <span style="color: #000000;">:|=======</span> <span style="color: #000000;"> 共耗时:</span> <span style="color: #000000;">0.57321000099182</span> <span style="color: #000000;">,共用内存:</span> <span style="color: #000000;">578172</span> <span style="color: #000000;"> Start @</span> <span style="color: #000000;">1287562244.1532</span> <span style="color: #000000;">(</span> <span style="color: #000000;">1587544</span> <span style="color: #000000;">)</span> <span style="color: #000000;">|-------></span> <span style="color: #008080;">End</span> <span style="color: #000000;"> @</span> <span style="color: #000000;">1287562244.6921</span> <span style="color: #000000;">(</span> <span style="color: #000000;">1587744</span> <span style="color: #000000;">) </span> <span style="color: #000000;">:|=======</span> <span style="color: #000000;"> 共耗时:</span> <span style="color: #000000;">0.53887605667114</span> <span style="color: #000000;">,共用内存:</span> <span style="color: #000000;">200</span> <span style="color: #000000;"> </span> </p>
2 つのメソッドの時間が近づき始めている (そして通常の呼び出しの方が効率的である) ことを除けば、メモリには依然として大きな違いがあります。がっかりしてインターネットで調べてみると、誰かが同様のテストを行っていることがわかりました。結果を直接コピーします:
(結果を見るだけでは少しわかりにくいかもしれません。詳しい手順はこちらでご覧いただけます: http://vega.rd.no/articles/php-static-method-performance)
テスト結果 (時間順 DESC):
<p> <span style="color: #000000;"> </span> <span style="color: #000000;">============</span> <span style="color: #000000;">Which method</span> <span style="color: #000000;">========================</span> <span style="color: #008080;">Time</span> <span style="color: #000000;">======</span> <span style="color: #000000;"> Inline calculation </span> <span style="color: #000000;">0.0805</span> <span style="color: #000000;"> s Normal </span> <span style="color: #0000ff;">function</span> <span style="color: #000000;"> call </span> <span style="color: #000000;">0.3438</span> <span style="color: #000000;"> s Normal method called through </span> <span style="color: #0000ff;">object</span> <span style="color: #000000;"> </span> <span style="color: #000000;">0.4118</span> <span style="color: #000000;"> s </span> <span style="color: #0000ff;">Static</span> <span style="color: #000000;"> method called statically </span> <span style="color: #000000;">0.4280</span> <span style="color: #000000;"> s Unspecified method called through </span> <span style="color: #0000ff;">object</span> <span style="color: #000000;">() </span> <span style="color: #000000;">0.4294</span> <span style="color: #000000;"> s Unspecified method called statically() </span> <span style="color: #000000;">0.6960</span> <span style="color: #000000;"> s </span> </p>
この観点から見ると、非静的メソッドを静的に呼び出すことにはパフォーマンスとメモリの点で何の利点もありません。また、この種のメソッドの呼び出しはメンテナンスが混乱しやすいです。したがって、短くても強力な要約として、非静的メソッドを静的に呼び出すことはお勧めできません。 [code=PHP][/code][code=PHP][/code]