ホームページ ウェブフロントエンド jsチュートリアル PHP後期静的バインディング解析と応用の詳細説明

PHP後期静的バインディング解析と応用の詳細説明

May 26, 2018 pm 05:45 PM
php 分析する バインディング

この記事は、PHP の後期静的バインディング分析と応用に関する関連知識ポイントをまとめたもので、興味のある方は学習してください。

基礎知識

1. 範囲解決演算子 (::)

  • は、静的メンバーやクラス定数にアクセスするために使用でき、クラス内のプロパティやメソッドをオーバーライドするためにも使用できます。

  • 3 つの特別なキーワード self、parent、static は、クラス定義内のプロパティまたはメソッドにアクセスするために使用されます。

  • parent は、親クラスでオーバーライドされたプロパティまたはメソッドを呼び出すために使用されます (それが表示される場合、対応するクラスの親クラスに解決されます)。

  • self は、このクラスのメソッドまたはプロパティを呼び出すために使用されます (これが表示される場合、対応するクラスに解析されます。$this との違いに注意してください。$this は、現在インスタンス化されているオブジェクトを指します)。

  • サブクラスが親クラスのメソッドをオーバーライドする場合、PHP は親クラスでオーバーライドされたメソッドを呼び出しません。親クラスのメソッドを呼び出すかどうかは子クラスに依存します。

2. PHP カーネルはクラスの継承実装を「コンパイルフェーズ」に置きます

<?php
class A{
 const H = &#39;A&#39;;

 const J = &#39;A&#39;;

 static function testSelf(){
  echo self::H; //在编译阶段就确定了 self解析为 A
 }
}

class B extends A{
 const H = "B";

 const J = &#39;B&#39;;

 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 = &#39;C&#39;;
}

B::testParent();
B::testSelf();

echo "\n";

C::testParent();
C::testSelf();
ログイン後にコピー

実行結果:

AA
AA


結論:


自分: : およびparent:: がクラス 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 = &#39;Foo&#39;;
$classname::aStaticMethod(); // 自PHP 5.3.0后,可以通过变量引用类
?>
ログイン後にコピー

b. 静的属性の例 (クラス属性定義に表示)

<?php
class Foo
{
 public static $my_static = &#39;foo&#39;;

 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 = &#39;Foo&#39;;
print $classname::$my_static . "\n"; // As of PHP 5.3.0

print Bar::$my_static . "\n";
$bar = new Bar();
print $bar->fooStatic() . "\n";
?>
ログイン後にコピー

c.位置: クラスメソッド内で、変数またはメソッドを変更するために使用されます)


以下の詳細な分析

遅延静的バインディング (遅延静的バインディング)


PHP 5.3.0 以降、PHP には遅延静的バインディングと呼ばれる機能が追加されました継承スコープ内で静的に呼び出されるクラスを参照するために使用されます。

1. 転送された通話と転送されていない通話

転送された通話:

は、self::、parent::、static::、および forward_static_call() の方法で行われる静的呼び出しを指します。


非転送呼び出し:

クラス名を明示的に指定する静的呼び出し (例: Foo::foo())


非静的呼び出し (例: $foo->foo())


2 . Post-static バインディングの仕組み

原則: 前回の「非転送呼び出し」のクラス名が保存されます。これは、転送呼び出しである静的呼び出しを呼び出す場合、実際に呼び出されるクラスは、前の非転送呼び出しのクラスであることを意味します。

分析例:

<?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 = &#39;Mango is&#39;;
 public static function fruit() {
  $args = func_get_args();
  echo static::NAME, " " . join(&#39; &#39;, $args) . "\n";
 }
}

class Orange extends Mango
{
 const NAME = &#39;Orange is&#39;;

 public static function fruit() {
  echo self::NAME, "\n";

  forward_static_call(array(&#39;Mango&#39;, &#39;fruit&#39;), &#39;my&#39;, &#39;favorite&#39;, &#39;fruit&#39;);
  forward_static_call(&#39;fruit&#39;, &#39;my&#39;, &#39;father\&#39;s&#39;, &#39;favorite&#39;, &#39;fruit&#39;);
 }
}

Orange::fruit(&#39;NO&#39;);

function fruit() {
 $args = func_get_args();
 echo "Apple is " . join(&#39; &#39;, $args). "\n";
}

?>


运行结果:
Orange is
Orange is my favorite fruit
Apple is my father&#39;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
ログイン後にコピー

Application

前述したように、遅延静的バインディングを導入する目的は次のとおりです: 継承スコープ内の静的参照の呼び出しクラス。

したがって、遅延静的バインディングを使用してシングルトン継承の問題を解決できます。

まず、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 の同じオブジェクトであることがわかります

静的はどのような結果を取得しますか?

<?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) {
}
ログイン後にコピー

上記は私がまとめたもので、将来的には皆さんのお役に立てば幸いです。

関連記事:

AjaxSubmit() はファイルを送信します

Ajax で冗長な更新を解決する 2 つの方法

Ajax の同期と非同期の問題と解決策

以上がPHP後期静的バインディング解析と応用の詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

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

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

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

Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Dec 24, 2024 pm 04:42 PM

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

CakePHP の日付と時刻 CakePHP の日付と時刻 Sep 10, 2024 pm 05:27 PM

Cakephp4 で日付と時刻を操作するには、利用可能な FrozenTime クラスを利用します。

CakePHP について話し合う CakePHP について話し合う Sep 10, 2024 pm 05:28 PM

CakePHP は、PHP 用のオープンソース フレームワークです。これは、アプリケーションの開発、展開、保守をより簡単にすることを目的としています。 CakePHP は、強力かつ理解しやすい MVC のようなアーキテクチャに基づいています。モデル、ビュー、コントローラー

CakePHP ファイルのアップロード CakePHP ファイルのアップロード Sep 10, 2024 pm 05:27 PM

ファイルのアップロードを行うには、フォーム ヘルパーを使用します。ここではファイルアップロードの例を示します。

CakePHP バリデータの作成 CakePHP バリデータの作成 Sep 10, 2024 pm 05:26 PM

Validator は、コントローラーに次の 2 行を追加することで作成できます。

PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 Dec 20, 2024 am 11:31 AM

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

CakePHP クイックガイド CakePHP クイックガイド Sep 10, 2024 pm 05:27 PM

CakePHP はオープンソースの MVC フレームワークです。これにより、アプリケーションの開発、展開、保守がはるかに簡単になります。 CakePHP には、最も一般的なタスクの過負荷を軽減するためのライブラリが多数あります。

PHPでHTML/XMLを解析および処理するにはどうすればよいですか? PHPでHTML/XMLを解析および処理するにはどうすればよいですか? Feb 07, 2025 am 11:57 AM

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

See all articles