PHP 静的バインディングの使用方法の詳細な説明
今回は、PHP の静的バインディングの使用方法について詳しく説明します。PHP の静的バインディングを使用する際の注意点を以下に示します。
基礎知識
1. 範囲解決演算子 (::)
は、静的メンバー、クラス定数にアクセスするために使用でき、クラス内の プロパティとメソッドをオーバーライドするためにも使用できます。
3 つの特別なキーワード self、parent、static は、クラス定義内のプロパティまたはメソッドにアクセスするために使用されます。
parent は、親クラスでオーバーライドされたプロパティまたはメソッドを呼び出すために使用されます (それが表示される場合、対応するクラスの親クラスに解決されます)。
self は、このクラスのメソッドまたはプロパティを呼び出すために使用されます (これが表示される場合、対応するクラスに解析されます。$this との違いに注意してください。$this は、現在インスタンス化されているオブジェクトを指します)。
サブクラスが親クラスのメソッドをオーバーライドする場合、PHP は親クラスでオーバーライドされたメソッドを呼び出しません。親クラスのメソッドを呼び出すかどうかは子クラスに依存します。
2. PHP カーネルはクラスの継承実装を「コンパイルフェーズ」に配置します
<?php class A{ const H = 'A'; const J = 'A'; static function testSelf(){ echo self::H; //在编译阶段就确定了 self解析为 A } } class B extends A{ const H = "B"; const J = 'B'; static function testParent(){ echo parent::J; //在编译阶段就确定了 parent解析为A } /* 若重写testSelf则能输出“B”, 且C::testSelf()也是输出“B” static function testSelf(){ echo self::H; } */ } class C extends B{ const H = "C"; const J = 'C'; } B::testParent(); B::testSelf(); echo "\n"; C::testParent(); C::testSelf();
実行結果:
AA
AA
結論:
self:: とparent:: が表示されます。 in 特定のクラス X の定義では、親クラスのメソッドがサブクラスでオーバーライドされない限り、対応するクラス X に解決されます。
3.Static(静的)キーワード
機能:
- 関数本体内の変数を変更するstaticキーワードは、静的なローカル変数を定義するために使用されます。
- クラスのメンバー関数とメンバー変数を変更するときに静的メンバーを宣言するために使用されます。
- (PHP5.3 以降) スコープ リゾルバー (::) の前の静的な遅延バインディングを表す特別なクラス。
例:
静的ローカル変数を定義する (出現: ローカル関数内)
特徴: 静的変数はローカル関数スコープ内にのみ存在しますが、プログラムの実行がこのスコープを離れても、その値は失われません。
<?php function test() { static $count = 0; $count++; echo $count; if ($count < 10) { test(); } $count--; }
静的メソッド、静的属性を定義する
a) クラスの属性またはメソッドを静的として宣言し、クラスをインスタンス化せずに直接アクセスできるようにします。
b) クラスのインスタンス化されたオブジェクトを通じて静的プロパティにアクセスすることはできません (ただし、静的メソッドはアクセスできます)
c) アクセス制御 が指定されていない場合、プロパティとメソッドはデフォルトで public になります。
d) 静的メソッドではオブジェクトを呼び出す必要がないため、疑似変数 $this は静的メソッドでは使用できません。
e) -> 演算子を使用してオブジェクトから静的プロパティにアクセスすることはできません。
f) 非静的メソッドを静的に呼び出すと、E_STRICT レベルのエラーが発生します。
g) 他のすべての PHP 静的変数と同様、静的プロパティは式ではなくリテラルまたは定数にのみ初期化できます。したがって、静的プロパティは整数または配列に初期化できますが、別の変数や関数の戻り値に初期化したり、オブジェクトを指すことはできません。
a. 静的メソッドの例 (クラス メソッドの定義に表示)
<?php class Foo { public static function aStaticMethod() { // ... } } Foo::aStaticMethod(); $classname = 'Foo'; $classname::aStaticMethod(); // 自PHP 5.3.0后,可以通过变量引用类 ?>
b. 静的属性の例 (クラス属性の定義に表示)
<?php class Foo { public static $my_static = 'foo'; public function staticValue() { return self::$my_static; //self 即 FOO类 } } class Bar extends Foo { public function fooStatic() { return parent::$my_static; //parent 即 FOO类 } } print Foo::$my_static . "\n"; $foo = new Foo(); print $foo->staticValue() . "\n"; print $foo->my_static . "\n"; // Undefined "Property" my_static print $foo::$my_static . "\n"; $classname = 'Foo'; print $classname::$my_static . "\n"; // As of PHP 5.3.0 print Bar::$my_static . "\n"; $bar = new Bar(); print $bar->fooStatic() . "\n"; ?>
c. 遅延静的バインディングに使用します。変数またはメソッドを変更するために使用されます)
以下は詳細な分析です
late static binding (遅延静的バインディング)PHP 5.3.0以降、PHPには静的に参照するために使用されるlate static bindingと呼ばれる機能が追加されました。継承スコープ内のクラスを呼び出します。1. 転送された通話と転送されていない通話
転送された通話:は、self::、parent::、static::、および forward_static_call() の方法で行われる静的呼び出しを指します。 非転送呼び出し: クラス名を明確に指定する静的呼び出し (Foo::foo() など) 非静的呼び出し ($foo->foo() など)2.後期静的バインディング作業の原則
原理:存储了在上一个“非转发调用”(non-forwarding call)中的类名。意思是当我们调用一个转发调用的静态调用时,实际调用的类是上一个非转发调用的类。
例子分析:
<?php class A { public static function foo() { echo CLASS."\n"; static::who(); } public static function who() { echo CLASS."\n"; } } class B extends A { public static function test() { echo "A::foo()\n"; A::foo(); echo "parent::foo()\n"; parent::foo(); echo "self::foo()\n"; self::foo(); } public static function who() { echo CLASS."\n"; } } class C extends B { public static function who() { echo CLASS."\n"; } } C::test(); /* * C::test(); //非转发调用 ,进入test()调用后,“上一次非转发调用”存储的类名为C * * //当前的“上一次非转发调用”存储的类名为C * public static function test() { * A::foo(); //非转发调用, 进入foo()调用后,“上一次非转发调用”存储的类名为A,然后实际执行代码A::foo(), 转 0-0 * parent::foo(); //转发调用, 进入foo()调用后,“上一次非转发调用”存储的类名为C, 此处的parent解析为A ,转1-0 * self::foo(); //转发调用, 进入foo()调用后,“上一次非转发调用”存储的类名为C, 此处self解析为B, 转2-0 * } * * * 0-0 * //当前的“上一次非转发调用”存储的类名为A * public static function foo() { * static::who(); //转发调用, 因为当前的“上一次非转发调用”存储的类名为A, 故实际执行代码A::who(),即static代表A,进入who()调用后,“上一次非转发调用”存储的类名依然为A,因此打印 “A” * } * * 1-0 * //当前的“上一次非转发调用”存储的类名为C * public static function foo() { * static::who(); //转发调用, 因为当前的“上一次非转发调用”存储的类名为C, 故实际执行代码C::who(),即static代表C,进入who()调用后,“上一次非转发调用”存储的类名依然为C,因此打印 “C” * } * * 2-0 * //当前的“上一次非转发调用”存储的类名为C * public static function foo() { * static::who(); //转发调用, 因为当前的“上一次非转发调用”存储的类名为C, 故实际执行代码C::who(),即static代表C,进入who()调用后,“上一次非转发调用”存储的类名依然为C,因此打印 “C” * } */ 故最终结果为: A::foo() A A parent::foo() A C self::foo() A C
3.更多静态后期静态绑定的例子
a)Self, Parent 和 Static的对比
<?php class Mango { function classname(){ return CLASS; } function selfname(){ return self::classname(); } function staticname(){ return static::classname(); } } class Orange extends Mango { function parentname(){ return parent::classname(); } function classname(){ return CLASS; } } class Apple extends Orange { function parentname(){ return parent::classname(); } function classname(){ return CLASS; } } $apple = new Apple(); echo $apple->selfname() . "\n"; echo $apple->parentname() . "\n"; echo $apple->staticname(); ?> 运行结果: Mango Orange Apple
b)使用forward_static_call()
<?php class Mango { const NAME = 'Mango is'; public static function fruit() { $args = func_get_args(); echo static::NAME, " " . join(' ', $args) . "\n"; } } class Orange extends Mango { const NAME = 'Orange is'; public static function fruit() { echo self::NAME, "\n"; forward_static_call(array('Mango', 'fruit'), 'my', 'favorite', 'fruit'); forward_static_call('fruit', 'my', 'father\'s', 'favorite', 'fruit'); } } Orange::fruit('NO'); function fruit() { $args = func_get_args(); echo "Apple is " . join(' ', $args). "\n"; } ?> 运行结果: Orange is Orange is my favorite fruit Apple is my father's favorite fruit
c)使用get_called_class()
<?php class Mango { static public function fruit() { echo get_called_class() . "\n"; } } class Orange extends Mango { // } Mango::fruit(); Orange::fruit(); ?> 运行结果: Mango Orange
应用
前面已经提到过了,引入后期静态绑定的目的是:用于在继承范围内引用静态调用的类。
所以, 可以用后期静态绑定的办法解决单例继承问题。
先看一下使用self是一个什么样的情况:
<?php // new self 得到的单例都为A。 class A { protected static $_instance = null; protected function construct() { //disallow new instance } protected function clone(){ //disallow clone } static public function getInstance() { if (self::$_instance === null) { self::$_instance = new self(); } return self::$_instance; } } class B extends A { protected static $_instance = null; } class C extends A{ protected static $_instance = null; } $a = A::getInstance(); $b = B::getInstance(); $c = C::getInstance(); var_dump($a); var_dump($b); var_dump($c); 运行结果: E:\code\php_test\apply\self.php:37: class A#1 (0) { } E:\code\php_test\apply\self.php:38: class A#1 (0) { } E:\code\php_test\apply\self.php:39: class A#1 (0) { }
通过上面的例子可以看到,使用self,实例化得到的都是类A的同一个对象
再来看看使用static会得到什么样的结果
<?php // new static 得到的单例分别为D,E和F。 class D { protected static $_instance = null; protected function construct(){} protected function clone() { //disallow clone } static public function getInstance() { if (static::$_instance === null) { static::$_instance = new static(); } return static::$_instance; } } class E extends D { protected static $_instance = null; } class F extends D{ protected static $_instance = null; } $d = D::getInstance(); $e = E::getInstance(); $f = F::getInstance(); var_dump($d); var_dump($e); var_dump($f); 运行结果: E:\code\php_test\apply\static.php:35: class D#1 (0) { } E:\code\php_test\apply\static.php:36: class E#2 (0) { } E:\code\php_test\apply\static.php:37: class F#3 (0) { }
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
以上がPHP 静的バインディングの使用方法の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











PHP 8.4 では、いくつかの新機能、セキュリティの改善、パフォーマンスの改善が行われ、かなりの量の機能の非推奨と削除が行われています。 このガイドでは、Ubuntu、Debian、またはその派生版に PHP 8.4 をインストールする方法、または PHP 8.4 にアップグレードする方法について説明します。

あなたが経験豊富な PHP 開発者であれば、すでにそこにいて、すでにそれを行っていると感じているかもしれません。あなたは、運用を達成するために、かなりの数のアプリケーションを開発し、数百万行のコードをデバッグし、大量のスクリプトを微調整してきました。

Visual Studio Code (VS Code とも呼ばれる) は、すべての主要なオペレーティング システムで利用できる無料のソース コード エディター (統合開発環境 (IDE)) です。 多くのプログラミング言語の拡張機能の大規模なコレクションを備えた VS Code は、

JWTは、JSONに基づくオープン標準であり、主にアイデンティティ認証と情報交換のために、当事者間で情報を安全に送信するために使用されます。 1。JWTは、ヘッダー、ペイロード、署名の3つの部分で構成されています。 2。JWTの実用的な原則には、JWTの生成、JWTの検証、ペイロードの解析という3つのステップが含まれます。 3. PHPでの認証にJWTを使用する場合、JWTを生成および検証でき、ユーザーの役割と許可情報を高度な使用に含めることができます。 4.一般的なエラーには、署名検証障害、トークンの有効期限、およびペイロードが大きくなります。デバッグスキルには、デバッグツールの使用とロギングが含まれます。 5.パフォーマンスの最適化とベストプラクティスには、適切な署名アルゴリズムの使用、有効期間を合理的に設定することが含まれます。

このチュートリアルでは、PHPを使用してXMLドキュメントを効率的に処理する方法を示しています。 XML(拡張可能なマークアップ言語)は、人間の読みやすさとマシン解析の両方に合わせて設計された多用途のテキストベースのマークアップ言語です。一般的にデータストレージに使用されます

文字列は、文字、数字、シンボルを含む一連の文字です。このチュートリアルでは、さまざまな方法を使用してPHPの特定の文字列内の母音の数を計算する方法を学びます。英語の母音は、a、e、i、o、u、そしてそれらは大文字または小文字である可能性があります。 母音とは何ですか? 母音は、特定の発音を表すアルファベットのある文字です。大文字と小文字など、英語には5つの母音があります。 a、e、i、o、u 例1 入力:string = "tutorialspoint" 出力:6 説明する 文字列「TutorialSpoint」の母音は、u、o、i、a、o、iです。合計で6元があります

静的結合(静的::) PHPで後期静的結合(LSB)を実装し、クラスを定義するのではなく、静的コンテキストで呼び出しクラスを参照できるようにします。 1)解析プロセスは実行時に実行されます。2)継承関係のコールクラスを検索します。3)パフォーマンスオーバーヘッドをもたらす可能性があります。

PHPの魔法の方法は何ですか? PHPの魔法の方法には次のものが含まれます。1。\ _ \ _コンストラクト、オブジェクトの初期化に使用されます。 2。\ _ \ _リソースのクリーンアップに使用される破壊。 3。\ _ \ _呼び出し、存在しないメソッド呼び出しを処理します。 4。\ _ \ _ get、dynamic属性アクセスを実装します。 5。\ _ \ _セット、動的属性設定を実装します。これらの方法は、特定の状況で自動的に呼び出され、コードの柔軟性と効率を向上させます。
