日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > php >内容正文

php

php self this static,PHP 中 self、static、$this 的区别和后期静态绑定详解

發(fā)布時(shí)間:2023/12/20 php 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 php self this static,PHP 中 self、static、$this 的区别和后期静态绑定详解 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本篇文章給大家分享的內(nèi)容是關(guān)于PHP 中 self、static、$this 的區(qū)別和后期靜態(tài)綁定詳解,有著一定的參考價(jià)值,有需要的朋友可以參考一下

self、static 和 $this 的區(qū)別

為了更好地理解 self、static 和 $this 的區(qū)別,先來看一個(gè)示例。<?phpclass A { protected $name = 'A'; static $alias = 'a'; const HASH = 'md5'; public function dd() { echo $this->name; echo '--'; echo static::$alias; echo '--'; // 后期靜態(tài)綁定

echo static::HASH; echo '--'; // 后期靜態(tài)綁定

echo self::$alias; echo '--'; echo self::HASH; echo '--';

var_dump(new self); echo '--';

var_dump($this); echo '--';

var_dump(new static); echo '
'; // 后期靜態(tài)綁定

} public static function who() { echo __CLASS__; echo ' [ This is A ]'; echo '
';

} public static function test() { self::who();

} public static function test2() { static::who(); // 后期靜態(tài)綁定

} public static function getInstance() {

var_dump(new self); echo '--';

var_dump(new static); echo '
'; // 后期靜態(tài)綁定

}

}class B extends A { protected $name = 'B'; static $alias = 'b'; const HASH = 'sha1'; public static function who() { echo __CLASS__; echo ' [ This is B ]'; echo '
';

}

}class C extends B { public static function who() { echo __CLASS__; echo ' [ This is C]'; echo '
';

}

}

(new A)->dd(); // A--a--md5--a--md5--object(A)#2 (1) { ["name":protected]=> string(1) "A" } --object(A)#1 (1) { ["name":protected]=> string(1) "A" } --object(A)#2 (1) { ["name":protected]=> string(1) "A" }(new B)->dd(); // B--b--sha1--a--md5--object(A)#2 (1) { ["name":protected]=> string(1) "A" } --object(B)#1 (1) { ["name":protected]=> string(1) "B" } --object(B)#2 (1) { ["name":protected]=> string(1) "B" }A::who(); // A [ This is A ]B::who(); // B [ This is B ]A::test(); // A [ This is A ]B::test(); // A [ This is A ]A::test2(); // A [ This is A ]B::test2(); // B [ This is B ]C::test2(); // C [ This is C]A::getInstance(); // object(A)#1 (1) { ["name":protected]=> string(1) "A" } --object(A)#1 (1) { ["name":protected]=> string(1) "A" }B::getInstance(); // object(A)#1 (1) { ["name":protected]=> string(1) "A" } --object(B)#1 (1) { ["name":protected]=> string(1) "B" }

總結(jié)說明:self 和 __CLASS__,都是對當(dāng)前類的靜態(tài)引用,取決于定義當(dāng)前方法所在的類。也就是說,self 寫在哪個(gè)類里面, 它引用的就是誰。

$this 指向的是實(shí)際調(diào)用時(shí)的對象,也就是說,實(shí)際運(yùn)行過程中,誰調(diào)用了類的屬性或方法,$this 指向的就是哪個(gè)對象。但 $this 不能訪問類的靜態(tài)屬性和常量,且 $this 不能存在于靜態(tài)方法中。

static 關(guān)鍵字除了可以聲明類的靜態(tài)成員(屬性和方法)外,還有一個(gè)非常重要的作用就是后期靜態(tài)綁定。

self 可以用于訪問類的靜態(tài)屬性、靜態(tài)方法和常量,但 self 指向的是當(dāng)前定義所在的類,這是 self 的限制。

$this 指向的對象所屬的類和 static 指向的類相同。

static 可以用于靜態(tài)或非靜態(tài)方法中,也可以訪問類的靜態(tài)屬性、靜態(tài)方法、常量和非靜態(tài)方法,但不能訪問非靜態(tài)屬性。

靜態(tài)調(diào)用時(shí),static 指向的是實(shí)際調(diào)用時(shí)的類;非靜態(tài)調(diào)用時(shí),static 指向的是實(shí)際調(diào)用時(shí)的對象所屬的類。

后期靜態(tài)綁定

后期靜態(tài)綁定(也叫延遲靜態(tài)綁定),可用于在繼承范圍內(nèi)引用靜態(tài)調(diào)用的類,也就是代碼運(yùn)行時(shí)最初調(diào)用的類。

后期靜態(tài)綁定本想通過引入一個(gè)新的關(guān)鍵字來表示,但最終還是沿用了 static 關(guān)鍵字。

工作原理

確切地說,static 后期靜態(tài)綁定的工作原理是存儲了上一個(gè)非轉(zhuǎn)發(fā)調(diào)用(non-forwarding call)的類名。

當(dāng)進(jìn)行靜態(tài)方法調(diào)用時(shí),該類名(static指向的類名)為明確指定的那個(gè)(通常是 :: 運(yùn)算符的左側(cè)部分),即實(shí)際調(diào)用時(shí)的類。

如上述示例中的:A::test2(); B::test2();

static 和 self 的區(qū)別:self 可以用于訪問類的靜態(tài)屬性、靜態(tài)方法和常量,但 self 指向的是當(dāng)前定義所在的類,這是 self 的限制。

static 也可以用于訪問類的靜態(tài)屬性、靜態(tài)方法和常量,static 指向的是實(shí)際調(diào)用時(shí)的類。

當(dāng)進(jìn)行非靜態(tài)方法調(diào)用時(shí),該類名(static指向的類名)為該對象所屬的類,即實(shí)際調(diào)用時(shí)的對象所屬的類。

如上述示例中的:(new A)->dd();

(new B)->dd();

static 和 $this 有點(diǎn)類似,但又有區(qū)別:$this 指向的對象所屬的類和 static 指向的類相同。

$this 不能用于靜態(tài)方法中,也不能訪問類的靜態(tài)屬性和常量。

$this 指向的是實(shí)際調(diào)用的對象。

static 可以用于靜態(tài)或非靜態(tài)方法中,也可以訪問類的靜態(tài)屬性、靜態(tài)方法、常量和非靜態(tài)方法,但不能訪問非靜態(tài)屬性。

static 指向的是實(shí)際調(diào)用時(shí)的對象所屬的類。

轉(zhuǎn)發(fā)調(diào)用(forwarding call)

所謂的轉(zhuǎn)發(fā)調(diào)用(forwarding call)指的是通過以下幾種方式進(jìn)行的靜態(tài)調(diào)用:self::,parent::,static:: 以及 forward_static_call() 。

可用 get_called_class() 函數(shù)來獲取被調(diào)用的方法所在的類名。

以下四種形式的調(diào)用,都是轉(zhuǎn)發(fā)調(diào)用:self::

parent::

static::

forward_static_call()

除此之外的調(diào)用,就是非轉(zhuǎn)發(fā)調(diào)用。

非轉(zhuǎn)發(fā)調(diào)用(non-forwarding call)

后期靜態(tài)綁定的工作原理是存儲了上一個(gè)非轉(zhuǎn)發(fā)調(diào)用(non-forwarding call)的類名。

通過具體的類名或具體的對象進(jìn)行的調(diào)用都是非轉(zhuǎn)發(fā)調(diào)用。

比如:A::test2();

B::test2();

(new A)->dd();

(new B)->dd();

注意事項(xiàng)

非靜態(tài)環(huán)境下的私有方法的查找順序

在非靜態(tài)環(huán)境下,在類的非靜態(tài)方法中,使用 $this 和 static 調(diào)用類的私有方法時(shí),執(zhí)行方式有所不同。$this 會優(yōu)先尋找所在定義范圍(父類)中的私有方法,如果存在就調(diào)用。

static 是先到它指向的類(子類)中尋找私有方法,如果找到了就會報(bào)錯(cuò),因?yàn)樗接蟹椒ㄖ荒茉谒x的類內(nèi)部調(diào)用;如果沒找到,再去所在定義范圍(父類)中尋找該私有方法,如果存在就調(diào)用。

具體來說,$this 會先到所在定義范圍內(nèi)尋找私有方法,再到它指向的對象所屬的類中尋找私有方法,然后尋找公有方法,最后到所在定義范圍內(nèi)尋找公共方法。只要找到了匹配的方法,就調(diào)用,并停止查找。

而 static 則是先到它指向的類中尋找私有方法,再尋找共有方法;然后到所在定義范圍內(nèi)尋找私有方法,再尋找共有方法。只要找到了匹配的方法,就調(diào)用,并停止查找。

下面是一個(gè)例子:<?php

class A { private function foo () {

var_dump($this); echo '--';

var_dump(new static); echo '--'; echo __CLASS__; echo '--'; echo get_called_class(); echo '
';

} public function test () { $this -> foo (); static:: foo (); echo '
';

}

}class B extends A { }class C extends A { private function foo () { echo 'this is C';

}

}

(new B())->test();

(new C())->test();

輸出結(jié)果為:object(B)#1 (0) { } --object(B)#2 (0) { } --A--B

object(B)#1 (0) { } --object(B)#2 (0) { } --A--B

object(C)#1 (0) { } --object(C)#2 (0) { } --A--C

Fatal error: Uncaught Error: Call to private method C::foo() from context 'A'

關(guān)于后期靜態(tài)綁定的解析

后期靜態(tài)綁定的解析會一直到取得一個(gè)完全解析了的靜態(tài)調(diào)用為止。如果靜態(tài)調(diào)用使用了 parent:: 或者 self:: 等轉(zhuǎn)發(fā)調(diào)用的形式,將會轉(zhuǎn)發(fā)調(diào)用信息。<?phpclass A { public static function foo () { static:: who ();

} public static function who () { echo __CLASS__ . "\n" ;

}

}class B extends A { public static function test () {

A :: foo (); parent :: foo (); self :: foo (); static::foo();

forward_static_call(['A', 'foo']); echo '
';

} public static function who () { echo __CLASS__ . "\n" ;

}

}class C extends B { public static function who () { echo __CLASS__ . "\n" ;

} public static function test2() { self::test();

}

}class D extends C { public static function who () { echo __CLASS__ . "\n" ;

}

}

B::foo();

B::test();

C::foo();

C::test();

D::foo();

D::test2();

以上的輸出結(jié)果為:B A B B B B

C A C C C C D A D D D D

static 后期靜態(tài)綁定的工作原理是存儲了上一個(gè)非轉(zhuǎn)發(fā)調(diào)用(non-forwarding call)的類名。請記住這句話。

下面的例子是非轉(zhuǎn)發(fā)調(diào)用。A::foo(); // 輸出 AB::foo(); // 輸出 BC::foo(); // 輸出 C

后期靜態(tài)綁定 static ,是定義在了 foo() 方法中,哪個(gè)類通過非轉(zhuǎn)發(fā)調(diào)用的形式調(diào)用 foo() 方法, foo() 方法中的 static 指向的就是哪個(gè)類。

但是,如果通過轉(zhuǎn)發(fā)調(diào)用的形式,調(diào)用 foo() 方法,如:parent :: foo ();self :: foo ();static::foo();forward_static_call(['A', 'foo']);

那么,就以轉(zhuǎn)發(fā)調(diào)用代碼所在的方法 test() 為準(zhǔn),哪個(gè)類通過非轉(zhuǎn)發(fā)調(diào)用的形式調(diào)用 test() 方法, foo() 方法中的 static 指向的就是哪個(gè)類。

假如調(diào)用 test() 方法時(shí),也采用了轉(zhuǎn)發(fā)調(diào)用的形式,如:public static function test2() { self::test();

}

那么,就以 test2() 方法為準(zhǔn) ... 依次類推。

也就是說,在使用了后期靜態(tài)綁定的基類中,后期靜態(tài)綁定所在的方法如果被轉(zhuǎn)發(fā)調(diào)用,則 static 的指向,會一直向上追溯,直到遇到非轉(zhuǎn)發(fā)調(diào)用的形式。

相關(guān)推薦:

總結(jié)

以上是生活随笔為你收集整理的php self this static,PHP 中 self、static、$this 的区别和后期静态绑定详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。