亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 語言 > PHP > 正文

詳解PHP后期靜態綁定分析與應用

2024-05-05 00:02:46
字體:
來源:轉載
供稿:網友

基礎知識

1. 范圍解析操作符 (::)

  • 可以用于訪問靜態成員,類常量,還可以用于覆蓋類中的屬性和方法。
  • self,parent 和 static 這三個特殊的關鍵字是用于在類定義的內部對其屬性或方法進行訪問的。
  • parent用于調用父類中被覆蓋的屬性或方法(出現在哪里,就將解析為相應類的父類)。
  • self用于調用本類中的方法或屬性(出現在哪里,就將解析為相應的類;注意與$this區別,$this指向當前實例化的對象)。
  • 當一個子類覆蓋其父類中的方法時,PHP 不會調用父類中已被覆蓋的方法。是否調用父類的方法取決于子類。

2. PHP內核將類的繼承實現放在了"編譯階段"

<?phpclass 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::出現在某個類X的定義中,則將被解析為相應的類X,除非在子類中覆蓋父類的方法。

3.Static(靜態)關鍵字

作用:

- 在函數體內的修飾變量的static關鍵字用于定義靜態局部變量。
- 用于修飾類成員函數和成員變量時用于聲明靜態成員。
- (PHP5.3之后)在作用域解析符(::)前又表示靜態延遲綁定的特殊類。

例子:

定義靜態局部變量(出現位置:局部函數中)

特征:靜態變量僅在局部函數域中存在,但當程序執行離開此作用域時,其值并不丟失。

<?phpfunction test(){ static $count = 0; $count++; echo $count; if ($count < 10) {  test(); } $count--;}

定義靜態方法,靜態屬性

a)聲明類屬性或方法為靜態,就可以不實例化類而直接訪問。

b)靜態屬性不能通過一個類已實例化的對象來訪問(但靜態方法可以)

c)如果沒有指定訪問控制,屬性和方法默認為公有。

d)由于靜態方法不需要通過對象即可調用,所以偽變量 $this 在靜態方法中不可用。

e)靜態屬性不可以由對象通過 -> 操作符來訪問。

f)用靜態方式調用一個非靜態方法會導致一個 E_STRICT 級別的錯誤。

g)就像其它所有的 PHP 靜態變量一樣,靜態屬性只能被初始化為文字或常量,不能使用表達式。所以可以把靜態屬性初始化為整數或數組,但不能初始化為另一個變量或函數返回值,也不能指向一個對象。

a.靜態方法例子(出現位置: 類的方法定義)

<?phpclass Foo { public static function aStaticMethod() {  // ... }}Foo::aStaticMethod();$classname = 'Foo';$classname::aStaticMethod(); // 自PHP 5.3.0后,可以通過變量引用類?> 

b.靜態屬性例子(出現位置:類的屬性定義)

<?phpclass 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.0print Bar::$my_static . "/n";$bar = new Bar();print $bar->fooStatic() . "/n";?>

c.用于后期靜態綁定(出現位置: 類的方法中,用于修飾變量或方法)

下面詳細分析

后期靜態綁定(late static binding)

自 PHP 5.3.0 起,PHP 增加了一個叫做后期靜態綁定的功能,用于在繼承范圍內引用靜態調用的類。

1.轉發調用與非轉發調用

轉發調用 :

指的是通過以下幾種方式進行的靜態調用:self::,parent::,static:: 以及 forward_static_call()。

非轉發調用 :

明確指定類名的靜態調用(例如Foo::foo())

非靜態調用(例如$foo->foo())

2.后期靜態綁定工作原理

原理:存儲了在上一個“非轉發調用”(non-forwarding call)中的類名。意思是當我們調用一個轉發調用的靜態調用時,實際調用的類是上一個非轉發調用的類。

例子分析:

<?phpclass 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()AAparent::foo()ACself::foo()AC

3.更多靜態后期靜態綁定的例子

a)Self, Parent 和 Static的對比

<?phpclass 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();?>運行結果:MangoOrangeApple

b)使用forward_static_call()

<?phpclass 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 isOrange is my favorite fruitApple is my father's favorite fruit

c)使用get_called_class()

<?phpclass Mango { static public function fruit() {  echo get_called_class() . "/n"; }}class Orange extends Mango { //}Mango::fruit();Orange::fruit();?>運行結果:MangoOrange

應用

前面已經提到過了,引入后期靜態綁定的目的是:用于在繼承范圍內引用靜態調用的類。
所以, 可以用后期靜態綁定的辦法解決單例繼承問題。

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

可以看到,使用static可以解決self時出現的單例繼承問題。


注:相關教程知識閱讀請移步到PHP教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品福利视频导航| 国产视频丨精品|在线观看| 国产欧美日韩高清| 青青久久av北条麻妃黑人| 国产成人综合精品| 久久久久99精品久久久久| 久久久久久亚洲精品| 日韩黄在线观看| 欧美在线视频免费| 51色欧美片视频在线观看| 美女国内精品自产拍在线播放| 久久五月天色综合| 色午夜这里只有精品| 成人黄色片在线| 久久这里只有精品视频首页| 搡老女人一区二区三区视频tv| 国产精品入口福利| 成人网中文字幕| 久久精品美女视频网站| 久久久精品久久久久| 日韩大陆毛片av| 中日韩美女免费视频网址在线观看| 日韩视频精品在线| 精品无码久久久久久国产| 亚洲精品电影在线观看| 精品国产乱码久久久久久天美| 色先锋资源久久综合5566| 亚洲免费视频一区二区| 日韩精品久久久久| 亚洲区免费影片| 欧美视频第一页| 欧美大码xxxx| 91精品国产九九九久久久亚洲| 日韩中文字幕免费视频| 日本91av在线播放| 成人亚洲综合色就1024| 搡老女人一区二区三区视频tv| 久久免费观看视频| 91色琪琪电影亚洲精品久久| 亚洲国产日韩欧美在线99| 亚洲激情视频在线播放| 日韩精品在线免费观看视频| 亚洲欧美国产va在线影院| 国产视频精品xxxx| 国产精品久久久久免费a∨| 日韩免费在线电影| 精品久久久久久久久久| 国产精品久久久亚洲| 992tv在线成人免费观看| 亚洲欧美日韩区| 77777少妇光屁股久久一区| 中文.日本.精品| 性色av一区二区三区在线观看| 久久91亚洲人成电影网站| 日韩电影中文 亚洲精品乱码| 亚洲精品电影网| 91精品国产九九九久久久亚洲| 日韩高清av一区二区三区| 国产成人97精品免费看片| 国产欧美一区二区三区久久人妖| 亚洲丝袜一区在线| 日韩欧美在线字幕| 亚洲精品成人免费| 国产91精品最新在线播放| 欧美一性一乱一交一视频| xvideos亚洲人网站| 久久久精品一区| 自拍视频国产精品| 亚洲成人av片在线观看| 亚洲欧美在线播放| 中文字幕在线成人| 韩国一区二区电影| 88xx成人精品| 国产三级精品网站| 亚洲人a成www在线影院| 久久频这里精品99香蕉| 欧美久久精品一级黑人c片| 91视频国产高清| 亚洲自拍偷拍色图| 久久噜噜噜精品国产亚洲综合| 一区二区亚洲欧洲国产日韩| 日产精品久久久一区二区福利| 欧美性一区二区三区| 91性高湖久久久久久久久_久久99| 亚洲精选在线观看| 日韩中文有码在线视频| 欧美日韩精品二区| 九九九热精品免费视频观看网站| 91国产中文字幕| 操91在线视频| 亚洲伊人第一页| 日韩成人小视频| 欧美性生交大片免费| 国产成人精品综合久久久| 亚洲最新视频在线| 亚洲欧洲日产国产网站| 国产亚洲美女久久| 国产不卡在线观看| 久久99久久99精品中文字幕| 97国产真实伦对白精彩视频8| 久久久精品免费视频| 国产日韩欧美自拍| 国产a∨精品一区二区三区不卡| 亚洲精品一区中文| 亚洲国产另类 国产精品国产免费| 88国产精品欧美一区二区三区| 欧美成人精品在线视频| 国产成人免费av| 亚洲男人天堂久| 亚洲国产另类 国产精品国产免费| 日韩免费在线免费观看| 国产啪精品视频网站| 成人av在线网址| 亚洲欧美国产高清va在线播| 91精品国产91久久久久久最新| 国产精品久久久久久久电影| 久久人人爽国产| 日韩精品极品毛片系列视频| 成人欧美一区二区三区黑人| 日本精品久久久久影院| 日韩一区二区久久久| 中文字幕亚洲欧美日韩在线不卡| 欧美电影在线播放| 红桃av永久久久| 国产精品久久久av久久久| 欧美伊久线香蕉线新在线| 亚洲亚裔videos黑人hd| 日韩精品免费视频| 疯狂欧美牲乱大交777| 91精品国产色综合久久不卡98| 懂色av影视一区二区三区| 裸体女人亚洲精品一区| 大量国产精品视频| 日韩av网站在线| 91福利视频在线观看| 国产精品美女久久| 日韩精品在线观| 伊人久久大香线蕉av一区二区| 最近2019中文字幕在线高清| 黄色91在线观看| 欧美大尺度在线观看| 国产精品啪视频| 国产手机视频精品| 日本国产欧美一区二区三区| 国产精品日韩在线观看| 欧美日韩国产中文字幕| 精品视频在线播放| 久久久久国色av免费观看性色| 日韩男女性生活视频| 国产精品丝袜久久久久久高清| 欧美高清视频一区二区| 日韩在线观看你懂的| 欧美激情一二区| 欧洲成人在线视频| 日韩中文字幕在线观看| www.亚洲男人天堂| 一区二区三区视频在线| 国产一区二区三区视频| 国产自产女人91一区在线观看| 中文字幕av日韩| 精品久久久久久久久国产字幕| 亚洲精品99久久久久中文字幕| 日韩影视在线观看| 91精品国产91|