php繼承this-ag真人国际官网
a. 在php中self與$this的分別
1、意思上的區別
self代表類,$this代表對象(self是引用靜態類的類名,而$this是引用非靜態類的實例名)
2、用法上的區別
能用$this的地方一定使用self,能用self的地方不一定能用$this。
(1)php繼承this擴展閱讀:
python中self用法詳解
1、以student類為例,在python中,定義類如下:
class student(object):
pass
(object)表示該類從哪個類繼承下來的,object類是所有類都會繼承的類。
2、實例:定義好了類,就可以通過student類創建出student的實例,創建實例是通過類名 ()實現:
student = student()
3、由於類起到模板的作用,因此,可以在創建實例的時候,把我們認為必須綁定的屬性強制填寫進去。這里就用到python當中的一個內置方法__init__方法,例如在student類時,把name、score等屬性綁上去:
class student(object):
def __init__(self, name, score):
self.name = name
self.score = score
b. php中的類是單繼承,那要有多個類繼承怎麼辦
php沒有多繼承的特性。即使是一門支持多繼承的編程語言,我們也很少會使用這個特性。在大多數人看來,多繼承不是一種好的設計方法。想要給某個類添加額外的特性,不一定要使用繼承。這里我提供一種模擬多繼承的方法以供參考。
php有一個魔術方法,叫做__call。當你調用一個不存在的方法時,這個方法會被自動調用。這時,我們就有機會將調用重定向到一個存在的方法。繼承多個父類的子類,尋找方法的過程一般是這樣的:
本身的方法 -> 父類1的方法 -> 父類2的方法...
模擬過程大致是這樣:將各個父類實例化,然後作為子類的屬性。這些父類提供一些公有的方法。當子類擁有某方法時,__call()函數不會被調用。這相當於「覆蓋」了父類的方法。當調用了不存在的方法時,通過__call()方法依次從父類中尋找可以調用的方法。雖然這不是完備的多繼承,但可以幫助我們解決問題。
classparent1{
functionmethod1(){}
functionmethod2(){}
}
classparent2{
functionmethod3(){}
functionmethod4(){}
}
classchild{
protected$_parents=array();
publicfunctionchild(array$parents=array()){
$_parents=$parents;
}
publicfunction__call($method,$args){
//從「父類"中查找方法
foreach($this->_parentsas$p){
if(is_callable(array($p,$method))){
returncall_user_func_array(array($p,$method),$args);
}
}
//恢復默認的行為,會引發一個方法不存在的致命錯誤
returncall_user_func_array(array($this,$method),$args);
}
}
$obj=newchild(array(newparent1(),newparent2()));
$obj->method1();
$obj->method3();
這里沒有涉及屬性的繼承,但實現起來並不困難。可以通過__set()和__get()魔術方法來模擬屬性的繼承。請你動手實踐。
c. 在php里,子類是不是可以繼承父類的私有屬性,但不能訪問啊
用print_r來檢測一下這個對象
注釋掉的時候
print_r($s1);
student object
(
[name:person:private] => ys
)
告訴我們name是person類私有的屬性
當沒注釋掉的時候
print_r($s1);
student object
(
[name:person:private] => ys
[name] => 子類
)
告訴我們name是person類私有的屬性,有給student類添加了一個name屬性
我們還注釋掉,再修改如下
$s1 = new student();
$s1->name = '子類'; //添加一個屬性為name
$s1->say();
跟上面一樣的結果
從這些調試結果分析,繼承跟訪問可以這樣說是一個概念,私有不可以繼承過來。
你繼承的時候加的那個$this->name是又新添加了一個name屬性,跟父類的name屬性無關
d. php中this,self和static的區別
php支持類和面向對象結構,php的類的靜態函數和變數不與任何特定類的實例相關聯(換句話說,一個對象)。
相反,靜態函數和變數與類定義本身相關聯。換言之,一個類的所有實例都共享相同的靜態變數。在一個類的方法(函數)的上下文中,靜態變數和函數被訪問使用self::,在一個類的對象(實例)的上下文中使用其他方法和變數時用this。
靜態函數只能使用靜態變數,靜態函數和變數的引用是通過 self::函數名() 和 self::變數名。上述實例中,靜態變數的引用是由類名(exampleclass::$foo),或者self::(self::$foo),當在這個類的靜態方法[稱為 靜態函數()]里使用時。類的正則函數和變數需要一個對象上下文來引用,他們不能脫離對象上下文而存在。對象上下文由$this提供。在上述函數中,$bar 是一個正則變數,所以它被 $obj->bar(上下文使用變數obj) 來引用,或者使用 $this->bar(再次在一個對象的方法里在一個對象上下文中) 來引用。
self 不使用前面的 $,因為 self 不意味著是一個變數而是類結構本身。而 $this 引用一個特定的變數,所以有前面的 $ 。
e. php 類之間傳遞參數
1. 用繼承,b繼承a,其中a的mm方法裡面的參數k作為方法的返回值,這樣就可以給到a去使用了。
classbextendsa{
publicfunctiontt(){$k=$this->mm();}
}
2.在a類裡面實例化b類。
classa{
publicfunctiontt(){
$class=newb();
$k=$class->mm();
}
}
兩個方法的前提條件都是需要mm方法的k變數作為返回值,然後在a類調用的時候就可以得到這參數了。
3.將k參數儲存到a類的屬性中。
步驟大致和2方法差不多,也是要在tt方法裡面實例化b類,但是b類的mm方法改為:
publicfunctionmm()
{$this->k=$k;}
這樣就不用k為返回值了,然後在a類中這樣:
classa{
publicfunctiontt(){
$class=newb();
$class->mm();
$k=$class->k;
}
}
不保證代碼的完全正確,但是思路是對的。
f. 在php中,子類extends繼承了父類,當子類和父類同時存在構造函數__construct先執行哪一個呢
1、如果父類和子類中都沒有顯式的定義__construct,在實例化子類對象時,只會隱含的調用子類自己的構造方法。
2、如果父類中有顯式的構造方法__construct,而子類中沒有定義__construct,在實例化子類對象時,就會調用父類中的構造方法。
3、如果父類和子類中都顯式的定義了__construct,在實例化子類對象時,只會調用子類自己的構造方法(這就像是子類重構了父類的構造方法),而如果也想要調用父類的構造方法的話,就需要在子類的__construct 方法中顯式的調用,(如 __construct(){ parent::_construct();})。
(6)php繼承this擴展閱讀
子類的構造函數名與子類名相同。
在子類里父類的構造函數不會自動執行。
要在子類里執行父類的構造函數,必須執行類似以下語句:
$this->[父類的構造函數名()]
類的構造函數統一命名為__construct()。
子類的構造函數名也是__construct()(也是廢話)。
在子類里父類的構造函數會不會執行,分兩種情況:
1、如子類不定義構造函數 __construct(),則父類的構造函數默認會被繼承下來,且會自動執行。
2、如子類定義了構造函數 __construct(),因為構造函數名也是__construct(),所以子類的構造函數實際上是覆蓋(override)了父類的構造函數。這時執行的是該子類的構造函數。
這時如果要在子類里執行父類的構造函數,必須執行類似以下語句:parent::__construct();
g. php繼承的問題,調用父類的方法this指向問題。
我來說一說:
【一】…………public(僅有)屬性和方法的繼承…………
classa{
public$var='vara
';
publicfunctionm(){
echo'funa
';
}
publicfunctionrun(){
echo$this->var;
$this->m();
}
}
classbextendsa{
public$var='varb
';
publicfunctionm(){
echo'funb
';
}
}
$li=newb();
$li->run();
echo'
';
var_mp($li);
輸出:
varb
funb
————————————————————————————
object(b)[1]
public'var'=>string'varb
'(length=11)
在這段代碼中所表示的,是我們常見的一種繼承方式,同為公有屬性的$var 和公有方法m()
在這里,$var和m()都被繼承並覆寫,實例化過後,內存中只有一個$var實例,通過var_mp($li);我們可以看到它。
【二】…………private(私有)屬性和方法的繼承…………
classa{
private$var='vara
';
privatefunctionm(){
echo'funa
';
}
publicfunctionrun(){
echo$this->var;
$this->m();
var_mp($this);
echo'
';
}
}
classbextendsa{
private$var='varb
';
privatefunctionm(){
echo'funb
';
}
publicfunctionrun(){
echo$this->var;
$this->m();
var_mp($this);
echo'
';
parent::run();
}
}
$li=newb();
$li->run();
echo'
';
var_mp($li);
輸出:
varb
funb
object(b)[1]
private'var'=>string'varb
'(length=11)
private'var'(a)=>string'vara
'(length=11)
.
.
vara
funa
object(b)[1]
private'var'=>string'varb
'(length=11)
private'var'(a)=>string'vara
'(length=11)
.
————————————————————————————————
object(b)[1]
private'var'=>string'varb
'(length=11)
private'var'(a)=>string'vara
'(length=11)
這個時候,我們可以看到,在調用run方法時,首先它會調用到b類的私有屬性$var 和私有方法m(),隨後,又使用parent::run()調用父類的run()方法,我們可以看到,父類的run()方法調用後,它所調用的屬性和方法,都是a類的兩個私有屬性和方法,這種形式,和你的問題一致;
而它與$this指向無關,我們可以在這里看到,兩個$this都是指向b類。
而最有意思的是,在$li句柄中,我們卻看到了兩個屬性!一個是b類的屬性,一個是a類的屬性,這兩個屬性同時存在著,那麼,私有方法也自然是同時存在著。
【三】…………私有屬性和方法能不能被繼承…………
classa{
private$var='vara
';
privatefunctionm(){
echo'funa
';
}
}
classbextendsa{
publicfunctionrun(){
echo$this->var;
$this->m();
}
}
$li=newb();
$li->run();
輸出:
notice:undefinedproperty:b::$varine:...online9
fatalerror:calltoprivatemethoda::m()fromcontext'b'ine:...online10
這可以證明,私有屬性和方法,無法被繼承,所以,你的代碼示例中所說,將a類的m()方法更改為private後,會顯示aa的屬性,也就可以理解明白了。
h. php this和self的區別
面向對象編程(oop,object oriented programming)現已經成為編程人員的一項基本技能。利用oop的思想進行php的高級編程,對於提高php編程能力和規劃web開發構架都是很有意義的。
php5 經過重寫後,對oop的支持額有了很大的飛躍,成為了具備了大部分面向對象語言的特性的語言,比php4有了很多的面向對象的特性。這里我主要談的是 this,self,parent 三個關鍵字之間的區別。從字面上來理解,分別是指 這、自己、父親。先初步解釋一下,this是指向當前對象的指針(可以看成c裡面的指針),self是指向當前類的指針,parent是指向父類的指針。 我們這里頻繁使用指針來描述,是因為沒有更好的語言來表達。關於指針的概念,大家可以去參考網路。
下面我們就根據實際的例子結合來講講。
class name //建立了一個名為name的類
{
private $name; //定義屬性,私有
//定義構造函數,用於初始化賦值
function __construct( $name )
{
$this->name = $name; //這里已經使用了this指針語句①
}
//析構函數
function __destruct(){}
//列印用戶名成員函數
function printname()
{
print( $this->name ); //再次使用了this指針語句②,也可以使用echo輸出
}
}
$obj1 = new name( "pbphome" ); //實例化對象 語句③
//執行列印
$obj1->printname(); //輸出: pbphome
echo "
"; //輸出:回車
//第二次實例化對象
$obj2 = new name( "php" );
//執行列印
$obj2->printname(); //輸出:php
?>
說 明:上面的類分別在 語句①和語句②使用了this指針,那麼當時this是指向誰呢?其實this是在實例化的時候來確定指向誰,比如第一次實例化對象的時候(語句③),那 么當時this就是指向$obj1對象,那麼執行語句②的列印時就把 print( $this->name ),那麼當然就輸出了"pbphome"。第二個實例的時候,print( $this->name )變成了print( $obj2->name ),於是就輸出了"php"。所以說,this就是指向當前對象實例的指針,不指向任何其他對象或類。
{二}。php中this,self,parent的區別之二self篇
此篇我們就self的用法進行講解
首 先我們要明確一點,self是指向類本身,也就是self是不指向任何已經實例化的對象,一般self使用來指向類中的靜態變數。假如我們使用類裡面靜態 (一般用關鍵字static)的成員,我們也必須使用self來調用。還要注意使用self來調用靜態變數必須使用 :: (域運算符號),見實例。
class counter //定義一個counter的類
{
//定義屬性,包括一個靜態變數$firstcount,並賦初值0 語句①
private static $firstcount = 0;
private $lastcount;
//構造函數
function __construct()
{
$this->lastcount = self::$firstcount; //使用self來調用靜態變數 語句②
}
//列印lastcount數值
function printlastcount()
{
print( $this->lastcount );
}
}
//實例化對象
$obj = new counter();
$obj->printlastcount(); //執行到這里的時候,程序輸出 1
?>
這 里要注意兩個地方語句①和語句②。我們在語句①定義了一個靜態變數$firstcount,那麼在語句②的時候使用了self調用這個值,那麼這時候我們 調用的就是類自己定義的靜態變數$frestcount。我們的靜態變數與下面對象的實例無關,它只是跟類有關,那麼我調用類本身的的,那麼我們就無法使 用this來引用,因為self是指向類本身,與任何對象實例無關。然後前面使用的this調用的是實例化的對象$obj,大家不要混淆了。
關於self就說到這里,結合例子還是比較方便理解的。第二篇結束。
{三}php中this,self,parent的區別之三parent篇
此篇我們就parent的用法進行講解。
首先,我們明確,parent是指向父類的指針,一般我們使用parent來調用父類的構造函數。實例如下:
//建立基類animal
class animal
{
public $name; //基類的屬性,名字$name
//基類的構造函數,初始化賦值
public function __construct( $name )
{
$this->name = $name;
}
}
//定義派生類person 繼承自animal類
class person extends animal
{
public $personsex; //對於派生類,新定義了屬性$personsex性別、$personage年齡
public $personage;
//派生類的構造函數
function __construct( $personsex, $personage )
{
parent::__construct( "pbphome" ); //使用parent調用了父類的構造函數 語句①
$this->personsex = $personsex;
$this->personage = $personage;
}
//派生類的成員函數,用於列印,格式:名字 is name,age is 年齡
function printperson()
{
print( $this->name. " is " .$this->personsex. ",age is " .$this->personage );
}
}
//實例化person對象
$personobject = new person( "male", "21");
//執行列印
$personobject->printperson(); //輸出結果:pbphome is male,age is 21
?>
里 面同樣含有this的用法,大家自己分析。我們注意這么個細節:成員屬性都是public(公有屬性和方法,類內部和外部的代碼均可訪問)的,特別是父類 的,這是為了供繼承類通過this來訪問。關鍵點在語句①: parent::__construct( "heiyeluren" ),這時候我們就使用parent來調用父類的構造函數進行對父類的初始化,這樣,繼承類的對象就都給賦值了name為pbphome。我們可以測試下, 再實例化一個對象$personobject1,執行列印後name仍然是pbphome。
總結:this是指向對象實例的一個指針,在實例化的時候來確定指向;self是對類本身的一個引用,一般用來指向類中的靜態變數;parent是對父類的引用,一般使用parent來調用父類的構造函數。
i. php 父類為什麼能調用子類的屬性
在集成的時候父類的屬性會被保護。如果想要調用父類的屬性必須使用父類對象super去調用,不然訪問不了。你在子類中沒有x的屬性,所以在調用時使用this或super調用屬性,這個時候不論是this還是super調用的都是父類的x屬性。