Heim > Web-Frontend > js-Tutorial > Detaillierte Erläuterung der Verwendung der späten statischen Bindungsanalyse von PHP

Detaillierte Erläuterung der Verwendung der späten statischen Bindungsanalyse von PHP

php中世界最好的语言
Freigeben: 2018-05-03 17:19:15
Original
1300 Leute haben es durchsucht

Dieses Mal erkläre ich Ihnen ausführlich die Analyse und Verwendung der späten statischen Bindung von PHP. Das Folgende ist ein praktischer Fall.

Grundkenntnisse

1. Bereichsanalyseoperator (::)

    kann verwendet werden Es wird für den Zugriff auf statische Mitglieder und Klassenkonstanten verwendet und kann auch zum Überschreiben von
  • Eigenschaften und Methoden

    in der Klasse verwendet werden.

  • Die drei speziellen Schlüsselwörter self, parent und static werden verwendet, um auf ihre Eigenschaften oder Methoden innerhalb der Klassendefinition zuzugreifen.
  • parent wird verwendet, um überschriebene Eigenschaften oder Methoden in der übergeordneten Klasse aufzurufen (wo es erscheint, wird es in die übergeordnete Klasse der entsprechenden Klasse aufgelöst).
  • self wird verwendet, um Methoden oder Eigenschaften in dieser Klasse aufzurufen (wo immer es erscheint, wird es in die entsprechende Klasse geparst; beachten Sie den Unterschied zu $this, $this zeigt auf den aktuellen Wert instanziiertes Objekt).
  • Wenn eine Unterklasse eine Methode in ihrer übergeordneten Klasse überschreibt, ruft PHP die überschriebene Methode in der übergeordneten Klasse nicht auf. Ob die Methode der übergeordneten Klasse aufgerufen wird, hängt von der untergeordneten Klasse ab.
2. Der PHP-Kernel versetzt die Vererbungsimplementierung von Klassen in die „Kompilierungsphase“

<?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();
Nach dem Login kopieren
Ergebnisse ausführen:

AA
AA


Schlussfolgerung:

self:: und parent:: erscheinen in der Definition einer Klasse X und werden in die entsprechende Klasse geparst X, es sei denn, die Methode der übergeordneten Klasse wird in der Unterklasse überschrieben.

3.Statisches (statisches) Schlüsselwort

Funktion:

-
statischer Schlüssel für geänderte Variablen im Funktionskörper Wort

wird verwendet, um statische lokale Variablen zu definieren. - Wird zum Deklarieren statischer Mitglieder beim Ändern von Klassenmitgliedsfunktionen und Mitgliedsvariablen verwendet. - (nach PHP5.3) eine spezielle Klasse, die eine statische verzögerte Bindung vor dem Scope-Resolver darstellt (::).

Beispiel:

Statische lokale Variablen definieren (Vorkommen: in lokalen Funktionen)

Feature: Statische Variablen existieren nur im lokalen Funktionsbereich, aber wenn das Programm Sein Wert geht nicht verloren, wenn die Ausführung diesen Bereich verlässt.

<?php
function test()
{
 static $count = 0;
 $count++;
 echo $count;
 if ($count < 10) {
  test();
 }
 $count--;
}
Nach dem Login kopieren

Statische Methoden und statische Attribute definieren

a) Klassenattribute oder -methoden als statisch deklarieren, damit direkt auf sie zugegriffen werden kann, ohne die Klasse zu instanziieren.

b) Auf statische Eigenschaften kann nicht über ein instanziiertes Objekt einer Klasse zugegriffen werden (auf statische Methoden ist dies jedoch möglich).

c) Wenn keine

Zugriffskontrolle

angegeben ist, gelten Eigenschaften und Methoden Der Standardwert ist öffentlich. d) Da statische Methoden keinen Aufruf eines Objekts erfordern, ist die Pseudovariable $this in statischen Methoden nicht verfügbar.

e) Auf statische Eigenschaften können Objekte nicht über den ->-Operator zugreifen.

f) Der statische Aufruf einer nicht statischen Methode führt zu einem Fehler auf E_STRICT-Ebene.

g) Wie alle anderen statischen PHP-Variablen können statische Eigenschaften nur als Literale oder Konstanten initialisiert werden, nicht als Ausdrücke. Daher kann eine statische Eigenschaft mit einer Ganzzahl oder einem Array initialisiert werden, sie kann jedoch nicht mit einem anderen Variablen- oder Funktionsrückgabewert initialisiert werden und kann auch nicht auf ein Objekt verweisen.

a. Beispiel für eine statische Methode (erscheint in: Klassenmethodendefinition)

<?php
class Foo {
 public static function aStaticMethod() {
  // ...
 }
}
Foo::aStaticMethod();
$classname = &#39;Foo&#39;;
$classname::aStaticMethod(); // 自PHP 5.3.0后,可以通过变量引用类
?>
Nach dem Login kopieren

b. Beispiel für ein statisches Attribut (erscheint in: Klassenattributdefinition)

<?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 = 'Foo';
print $classname::$my_static . "\n"; // As of PHP 5.3.0
print Bar::$my_static . "\n";
$bar = new Bar();
print $bar->fooStatic() . "\n";
?>
Nach dem Login kopieren

c späte statische Bindung (Position: in Klassenmethoden, wird zum Ändern von Variablen oder Methoden verwendet)

Eine detaillierte Analyse unten

Späte statische Bindung (späte statische Bindung)

Seit PHP 5.3.0 hat PHP eine Funktion namens „späte statische Bindung“ hinzugefügt, die verwendet wird, um statisch aufgerufene Klassen im Vererbungsbereich zu referenzieren.

1. Weitergeleitete Anrufe und nicht weitergeleitete Anrufe

Weitergeleitete Anrufe:

bezieht sich auf statische Anrufe, die auf folgende Weise getätigt werden: selbst: :, parent::, static:: und forward_static_call().

Nicht weitergeleitete Aufrufe:

Statische Aufrufe, die explizit den Klassennamen angeben (z. B. Foo::foo())

Nicht statische Aufrufe (z. B. $foo-> ;foo( ))

2. Funktionsprinzip der späten statischen Bindung

原理:存储了在上一个“非转发调用”(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
Nach dem Login kopieren

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
Nach dem Login kopieren

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's favorite fruit
Nach dem Login kopieren

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
Nach dem Login kopieren

应用

前面已经提到过了,引入后期静态绑定的目的是:用于在继承范围内引用静态调用的类。
所以, 可以用后期静态绑定的办法解决单例继承问题。

先看一下使用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) {
}
Nach dem Login kopieren

通过上面的例子可以看到,使用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) {
}
Nach dem Login kopieren

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

用JS检测电脑配置(附代码)

Vue.js+Flask来构建单页的App(附代码)

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Verwendung der späten statischen Bindungsanalyse von PHP. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage