沒有廢話 广匙,我想直接拋出問題哩俭。
一比默、php繼承問題
上代碼恬总。
class father{
public function __construct(){
echo "類father";
}
}
class child extends father{
public function __construct(){
echo "類child";
}
}
$p=new child();
輸出結(jié)果: 類child
如果我們接觸過純面向?qū)ο蟮恼Z言 :c#/java;
按照他們的語法鸣峭,以上例子將會(huì)輸出 :
類father
類child
當(dāng)我們在new子類對象的時(shí)候宏所,編譯器應(yīng)該會(huì)實(shí)例化它的父類,以此來產(chǎn)生一個(gè)繼承鏈條摊溶,我們看到表面上php僅僅實(shí)例化了一個(gè)子類對象爬骤,這并不科學(xué),也是后續(xù)問題產(chǎn)生的一個(gè)根本原因:php到底存不存在繼承鏈莫换?
二霞玄、static 、self拉岁、parent這些關(guān)鍵字
class father{
public $a="father";
public function __construct(){
echo "類father";
}
public function Say(){
echo __CLASS__."say";
}
}
class child{
public function __construct(){
parent::construct();
self::Say();
static::Say();
$this->a;
echo "類 child";
}
}
$childs=new child();
如果php不存在繼承鏈坷剧,那么以上程序?qū)?bào)錯(cuò)。
所以php是存在繼承鏈喊暖。
并且以上存在一些語法規(guī)則惫企,子類可以通過self或者是static等關(guān)鍵字,去調(diào)用父類中可供調(diào)用的方法,和$this類似狞尔。
那么我們是不是就可以理解成:self::或者是static::語法丛版,指向了一個(gè)father類的實(shí)力對象? 要不然成員方法怎么調(diào)用偏序?
但是奇怪的是:static::/self:: 不能調(diào)用屬性字段(非靜態(tài))页畦,parent::也是如此。
這個(gè)就尷尬了研儒,憑什么非靜態(tài)的方法能調(diào)用豫缨,字段屬性就不行?
那么應(yīng)該推翻self::/static::是對象的引用端朵,他們應(yīng)該是類層面上的引用州胳。
產(chǎn)生了矛盾。
憑什么能調(diào)用成員的方法逸月,卻無法調(diào)用成員屬性栓撞?
答案存在于內(nèi)存分布上面:
我們知道內(nèi)存分為4部分:
- 棧
- 堆
- 靜態(tài)數(shù)據(jù)區(qū)
- 代碼區(qū)
實(shí)例化對象的時(shí)候,將屬性都存放到了堆里面碗硬。方法存在于代碼區(qū)瓤湘,調(diào)用的時(shí)候,根據(jù)類指針來尋找存放地址恩尾,進(jìn)行調(diào)用弛说。
我們可以大體了解到,屬性可以在代碼運(yùn)行時(shí)動(dòng)態(tài)改變值翰意。方法木人,一旦我們定義好之后,代碼編譯完成方法體就很難改變冀偶,所以在內(nèi)存中如此存放醒第,更加節(jié)約空間。
所以进鸠,不管是static 還是self稠曼、parent都是指向類指針,可以調(diào)用靜態(tài)變量客年,以及方法列表霞幅。
$this真正指向本對象。