快速瞭解PHP的物件導向_PHP教程

來源:互聯網
上載者:User

物件導向的概念

物件導向編程(Object Oriented Programming, OOP, 物件導向程式設計)是一種電腦編程架構,OOP的一條基本原則是電腦程式是由單個能夠起到子程式作用的單元或對象組合而成,OOP達到了軟體工程的三個目標:重用性、靈活性和擴充性。為了實現整體運算,每個對象都能夠接收資訊、處理資料和向其它對象發送資訊。物件導向一直是軟體開發領域內比較熱門的話題,首先,物件導向符合人類看待事物的一般規律。其次,採用物件導向方法可以使系統各部分各司其職、各盡所能。為編程人員敞開了一扇大門,使其編程的代碼更簡潔、更易於維護,並且具有更強的可重用性。有人說PHP不是一個真正的物件導向的語言,這是事實。PHP 是一個混合型語言,你可以使用OOP,也可以使用傳統的過程化編程。然而,對於大型項目,你可能需要在PHP 中使用純的OOP去聲明類,而且在你的項目裡只用對象和類。這個概念我先不多說了,因為有很多朋友遠離物件導向編程的主要原因就是一接觸物件導向概念的時候就理解不上去, 所以就不想去學下去了。等讀者看完整體內容後再去把概念搞明白吧。

什麼是類,什麼是對象,類和對象這間的關係

類的概念:類是具有相同屬性和服務的一組對象的集合。它為屬於該類的所有對象提供了統一的抽象描述,其內部包括屬性和服務兩個主要部分。在物件導向的程式設計語言中,類是一個獨立的程式單位,它應該有一個類名並包括屬性說明和服務說明兩個主要部分。

對象的概念:對象是系統中用來描述客觀事物的一個實體,它是構成系統的一個基本單位。一個對象由一組屬性和對這組屬性進行操作的一組服務組成。從更抽象的角度來說,對象是問題域或實現域中某些事物的一個抽象,它反映該事物在系統中需要儲存的資訊和發揮的作用;它是一組屬性和有權對這些屬性進行操作的一組服務的封裝體。客觀世界是由對象和對象之間的聯絡組成的。

類與對象的關係就如模具和鑄件的關係,類的執行個體化結果就是對象,而對一類對象的抽象就是類。類描述了一組有相同特性(屬性)和相同行為(方法)的對象。

上面大概就是它們的定義吧,也許你是剛接觸物件導向的朋友, 不要被概念的東西搞暈了,給你舉個例子吧,如果你去中關村想買幾台組裝的PC機,到了那裡你第一步要幹什麼,是不是裝機的工程師和你坐在一起,按你提供的資訊和你一起完成一個裝機的配置單呀,這個配置單就可以想象成是類,它就是一張紙,但是它上面記錄了你要買的PC機的資訊,如果用這個配置單買10台機器,那麼這10台機子,都是按這個配置單組成的,所以說這10台機子是一個類型的,也可以說是一類的。那麼什麼是對象呢,類的執行個體化結果就是對象,用這個配置單配置出來(執行個體化出來)的機子就是對象,是我們可以操作的實體,10台機子,10個對象。每台機子都是獨立的,只能說明他們是同一類的,對其中一個機做任何動作都不會影響其它9台機器,但是我對類修改,也就是在這個配置單上加一個或少一個配件,那麼裝出來的9個機子都改變了,這是類和對象的關係(類的執行個體化結果就是對象)。

什麼是物件導向編程

就不說他的概念,如果你想建立一個電腦教室,首先要有一個房間, 房間裡面要有N台電腦,有N張桌子, N把椅子, 白板, 投影機等等,這些是什麼,剛才咱們說了, 這就是對象,能看到的一個個的實體,可以說這個電腦教室的單位就是這一個個的實體物件, 它們共同組成了這個電腦教室,那麼我們是做程式,這和物件導向有什麼關係呢?開發一個系統程式和建一個電腦教室類似,你把每個獨立的功能模組抽象成類,形成對象,由多個對象組成這個系統,這些對象之間都能夠接收資訊、處理資料和向其它對象發送資訊等等相互作用。就構成了物件導向的程式。

如何抽象出一個類

上面已經介紹過了,物件導向程式的單位就是對象,但對象又是通過類的執行個體化出來的,所以我們首先要做的就是如何來聲明類,做出來一個類很容易,只要掌握基本的程式文法定義規則就可以做的出來,那麼痛點在那裡呢?一個項目要用到多少個類,用多少個對象,在那要定義類,定義一個什麼樣的類,這個類執行個體化出多少個對象,類裡面有多少個屬性,有多少個方法等等,這就需要讀者通過在實際的開發中就實際問題分析設計和總結了。

類的定義:  class 類名{ }

使用一個關鍵字class和後面加上一個你想要的類名以及加上一對大括弧, 這樣一個類的結構就定義出來了,只要在裡面寫代碼就可以了, 但是裡面寫什嗎? 能寫什嗎?怎樣寫才是一個完整的類呢?上面講過來,使用類是為了讓它執行個體出對象來給我們用,這就要知道你想要的是什麼樣的對象了,像上面我們講的一個裝機配置單上寫什麼,你裝出來的機子就有什麼。比如說,一個人就是一個對象,你怎麼把一個你看好的人推薦給你們領導呢?當然是越詳細越好了:

首先,你會介紹這個人姓名、性別、年齡、身高、體重、電話、家庭住址等等。

然後,你要介紹這個人能做什麼,可以開車,會說英語,可以使用電腦等等。

只要你介紹多一點,別人對這個人就多一點瞭解,這就是我們對一個人的描述, 現在我們總結一下,所有的對象我們用類去描述都是類似的,從上面人的描述可以看到, 做出一個類來,從定義的角度分兩部分,第一是從靜態上描述,第二是從動態上描述, 靜態上的描述就是我們所說的屬性,像上面我們看到的,人的姓名、性別、年齡、身高、體重、電話、家庭住址等等。動態上也就是人的這個對象的功能,比如這個人可以開車,會說英語,可以使用電腦等等,抽象成程式時,我們把動態寫成函數或者說是方法,函數和方法是一樣的。所以,所有類都是從屬性和方法這兩方面去寫, 屬性又叫做這個類的成員屬性,方法叫做這個類的成員方法。

class 人{
成員屬性:姓名、性別、年齡、身高、體重、電話、家庭住址
成員方法:可以開車, 會說英語, 可以使用電腦
}

通過在類定義中使用關鍵字" var "來聲明變數,即建立了類的屬性,雖然在聲明成員屬性的時候可以給定初始值, 但是在聲明類的時候給成員屬性初使值是沒有必要的,比如說要是把人的姓名賦上“張三”,那麼用這個類執行個體出幾十個人,這幾十個人都叫張三了,所以沒有必要, 我們在執行個體出對象後給成員屬性初始值就可以了。如: var $somevar;

 

上面就是一個類的聲明,從屬性和方法上聲明出來的一個類,但是成員屬性最好在聲明的時候不要給初始的值,因為我們做的人這個類是一個描述資訊,將來用它執行個體化對象,比如執行個體化出來10個人對象,那麼這10個人, 每一個人的名子,性別, 年齡都是不一樣的,所以最好不要在這個地方給成員屬性賦初值,而是對每個對象分別賦值的。

用同樣的辦法可以做出你想要的類了, 只要你能用屬性和方法能描述出來的實體都可以定義成類,去執行個體化對象。

為了加強你對類的理解,我們再做一個類,做一個形狀的類,形狀的範圍廣了點, 我們就做個矩形吧,先分析一下,想一想從兩方面分析,矩形的屬性都有什嗎?矩形的功能都有什嗎?

class 矩形  { //矩形的屬性 矩形的長;  矩形的寬; //矩形的方法 矩形的周長; 矩形的面積;}
 

如果用這個類來建立出多個矩形對象,每個矩形對象都有自己的長和寬, 都可以求出自己的周長和面積了。

如何執行個體化對象

我們上面說過物件導向程式的單位就是對象,但對象又是通過類的執行個體化出來的,既然我們類會聲明了,下一步就是執行個體化對象了。當定義好類後,我們使用new關鍵字來產生一個對象。

 

$p1=new Person();
  這條代碼就是通過類產生執行個體對象的過程,$p1就是我們執行個體出來的對象名稱,同理,$p2, $p3也是我們執行個體出來的對象名稱,一個類可以執行個體出多個對象,每個對象都是獨立的,上面的代碼相當於執行個體出來3個人來,每個人之間是沒有聯絡的,只能說明他們都是人類,每個人都有自己的姓名,性別和年齡的屬性,每個人都有說話和走路的方法,只要是類裡面體現出來的成員屬性和成員方法,執行個體化出來的對象裡面就包含了這些屬性和方法。

對像在PHP裡面和整型、浮點型一樣,也是一種資料類,都是儲存不同類型資料用的,在啟動並執行時候都要載入到記憶體中去用, 那麼對象在記憶體裡面是怎麼體現的呢?記憶體從羅輯上說大體上是分為4段, 棧空間段、堆空間段、程式碼片段、 初始化靜態段,程式裡面不同的聲明放在不同的記憶體段裡面,棧空間段是儲存佔用相同空間長度並且佔用空間小的資料類型的地方,比如說整型1, 10, 100, 1000, 10000, 100000等等,在記憶體裡面佔用空間是等長的,都是64位4個位元組。 那麼資料長度不定長,而且佔有空間很大的資料類型的資料放在那記憶體的那個段裡面呢?這樣的資料是放在堆記憶體裡面的。棧記憶體是可以直接存取的,而堆記憶體是不可以直接存取的記憶體。對於我們的對象來數就是一種大的資料類型而且是佔用空間不定長的類型,所以說對象是放在堆裡面的,但對象名稱是放在棧裡面的,這樣通過對象名稱就可以使用對象了。

$p1=new Person();
  對於這個條代碼, $p1是對象名稱在棧記憶體裡面,new Person()是真正的對象是在堆記憶體裡面的。

每個在堆裡面的執行個體對象是儲存屬性的,比如說,現在堆裡面的執行個體對象裡面都存有姓名、性別和年齡。每個屬性又都有一個地址。$p1=new Person();等號的右邊$p1是一個引用變數,通過賦值運算子“=”把對象的首地址賦給“$p1”這個引用變數,所以$p1是儲存物件首地址的變數,$p1放在棧記憶體裡邊,$p1相當於一個指標指向堆裡面的對象,所以我們可以通過$p1這個引用變數來操作對象,通常我們也稱對象引用為對象。

如何去使用對象中的成員

上面看到PHP對象中的成員有兩種一種是成員屬性,一種是成員方法。對象我們已經可以聲明了,$p1=new Person();怎麼去使用對象的成員呢?要想訪問對象中的成員就要使用一個特殊的操作符“->”來完成對象成員的訪問:

對象->屬性 $p1->name; $p2->age; $p3->sex;

對象->方法 $p1->say(); $p2->run();

name=”張三”;$p1->sex=”男”;$p1->age=20;//下面三行是訪問$p1對象的屬性echo “p1對象的名子是:”.$p1->name.”
”;echo “p1對象的性別是:”.$p1->sex.”
”;echo “p1對象的年齡是:”.$p1->age.”
”;//下面兩行訪問$p1對象中的方法$p1->say();  $p1->run();//下面三行是給$p2對象屬性賦值$p2->name=”李四”;$p2->sex=”女”;$p2->age=30;//下面三行是訪問$p2對象的屬性echo “p2對象的名子是:”.$p2->name.”
”;echo “p2對象的性別是:”.$p2->sex.”
”;echo “p2對象的年齡是:”.$p2->age.”
”;//下面兩行訪問$p2對象中的方法$p2->say();$p2->run();//下面三行是給$p3對象屬性賦值$p3->name=”王五”;$p3->sex=”男”;$p3->age=40;  //下面三行是訪問$p3對象的屬性echo “p3對象的名子是:”.$p3->name.”
”;echo “p3對象的性別是:”.$p3->sex.”
”;echo “p3對象的年齡是:”.$p3->age.”
”;//下面兩行訪問$p3對象中的方法$p3->say();$p3->run();?>

從上例中可以看出只是對象裡面的成員就要使用對象->屬性、對象->方法形式訪問,再沒有第二種方法來訪問對象中的成員了。

特殊的引用“$this”的使用

現在我們知道了如何訪問對象中的成員,是通過“對象->成員”的方式訪問的,這是在對象的外部去訪問對象中成員的形式,那麼如果我想在對象的內部,讓對象裡的方法訪問本對象的屬性,或是對象中的方法去調用本對象的其它方法這時我們怎麼辦?因為對象裡面的所有的成員都要用對象來調用,包括對象的內部成員之間的調用,所以在PHP裡面給我提供了一個本對象的引用$this, 每個對象裡面都有一個對象的引用$this來代表這個對象,完成對象內部成員的調用, this的本意就是“這個”的意思, 上面的執行個體裡面,我們執行個體化三個執行個體對象$P1、 $P2、 $P3,這三個對象裡面各自存在一個$this分別代表對象$p1、$p2、$p3 。

通過我們可以看到,$this就是對象內部代表這個對象的引用,在對象內部和調用本對象的成員和對象外部調用對象的成員所使用的方式是一樣的。

$this->屬性 $this->name; $this->age; $this->sex;

$this->方法 $this->say(); $this->run();

修改一下上面的執行個體,讓每個人都說出自己的名字,性別和年齡:

name." 性別:".$this->sex." 我的年齡是:".$this->age."
";}function run() //這個人可以走路的方法{echo "這個人在走路";}}$p1=new Person(); //建立執行個體對象$p1$p2=new Person(); //建立執行個體對象$p2$p3=new Person(); //建立執行個體對象$p3//下面三行是給$p1對象屬性賦值$p1->name="張三";$p1->sex="男";$p1->age=20;//下面訪問$p1對象中的說話方法$p1->say();//下面三行是給$p2對象屬性賦值$p2->name="李四";$p2->sex="女";$p2->age=30;//下面訪問$p2對象中的說話方法$p2->say();//下面三行是給$p3對象屬性賦值$p3->name="王五";$p3->sex="男";$p3->age=40;//下面訪問$p3對象中的說話方法$p3->say();?>

分析一下這個方法:
function say() //這個人可以說話的方法
{
echo "我的名子叫:".$this->name." 性別:".$this->sex." 我的年齡是:".$this->age."
";
}
  在$p1、$p2和$p3這三個對象中都有say()這個方法,$this分別代表這三個對象, 調用相應的屬性,列印出屬性的值,這就是在對象內部訪問對象屬性的方式, 如果相在say()這個方法裡調用run()這個方法也是可以的,在say()這個方法中使用$this->run()的方式來完成調用。

構造方法與析構方法

大多數類都有一種稱為建構函式的特殊方法。當建立一個對象時,它將自動調用建構函式,也就是使用new這個關鍵字來執行個體化對象的時候自動調用構造方法。

建構函式的聲明與其它操作的聲明一樣,只是其名稱必須是__construct( )。這是PHP5中的變化,以前的版本中,建構函式的名稱必須與類名相同,這種在PHP5中仍然可以用,但現在以經很少有人用了,這樣做的好處是可以使建構函式獨立於類名,當類名發生改變時不需要改相應的建構函式名稱了。為了向下相容,如果一個類中沒有名為__construct( )的方法,PHP將搜尋一個php4中的寫法,與類名相同名的構造方法。

在一個類中只能聲明一個構造方法,而是只有在每次建立對象的時候都會去調用一次構造方法,不能主動的調用這個方法,所以通常用它執行一些有用的初始化任務。比如對成屬性在建立對象的時候賦初值。

name賦初使值$this->name=$name;//通過構造方法傳進來的$sex給成員屬性$this->sex賦初使值$this->sex=$sex;//通過構造方法傳進來的$age給成員屬性$this->age賦初使值$this->age=$age;}//這個人的說話方法function say(){echo "我的名子叫:".$this->name." 性別:".$this->sex." 我的年齡是:".$this->age."
";}}//通過構造方法建立3個對象$p1、p2、$p3,分別傳入三個不同的實參為姓名、性別和年齡$p1=new Person(“張三”,”男”, 20);$p2=new Person(“李四”,”女”, 30);$p3=new Person(“王五”,”男”, 40);//下面訪問$p1對象中的說話方法$p1->say();//下面訪問$p2對象中的說話方法$p2->say();//下面訪問$p3對象中的說話方法$p3->say();?>

與建構函式相對的就是解構函式。解構函式是PHP5新添加的內容,在PHP4中沒有解構函式。解構函式允許在銷毀一個類之前執行的一些操作或完成一些功能,比如說關閉檔案,釋放結果集等,解構函式會在到某個對象的所有引用都被刪除或者當對象被顯式銷毀時執行,也就是對象在記憶體中被銷毀前調用解構函式。與建構函式的名稱類似,一個類的解構函式名稱必須是__destruct( )。解構函式不能帶有任何參數。

name賦初使值$this->name=$name;//通過構造方法傳進來的$sex給成員屬性$this->sex賦初使值$this->sex=$sex;//通過構造方法傳進來的$age給成員屬性$this->age賦初使值$this->age=$age;}//這個人的說話方法function say(){echo "我的名子叫:".$this->name." 性別:".$this->sex." 我的年齡是:".$this->age."
";}//這是一個解構函式,在對象銷毀前調用function __destruct(){echo “再見”.$this->name.”
”;  }//通過構造方法建立3個對象$p1、p2、$p3,分別傳入三個不同的實參為姓名、性別和年齡$p1=new Person(“張三”,”男”, 20);$p2=new Person(“李四”,”女”, 30);$p3=new Person(“王五”,”男”, 40);//下面訪問$p1對象中的說話方法$p1->say();//下面訪問$p2對象中的說話方法$p2->say();//下面訪問$p3對象中的說話方法$p3->say();?>

封裝性

封裝性是物件導向編程中的三大特性之一,封裝性就是把對象的屬性和服務結合成一個獨立的相同單位,並儘可能隱蔽對象的內部細節,包含兩個含義:1.把對象的全部屬性和全部服務結合在一起,形成一個不可分割的獨立單位(即對象)。2.資訊隱蔽,即儘可能隱蔽對象的內部細節,對外形成一個邊界〔或者說形成一道屏障〕,只保留有限的對外介面使之與外部發生聯絡。

封裝的原則在軟體上的反映是:要求使對象以外的部分不能隨意存取對象的內部資料(屬性),從而有效避免了外部錯誤對它的"交叉感染",使軟體錯誤能夠局部化,大大減少查錯和排錯的難度。

用個執行個體來說明吧,假如某個人的對象中有年齡和工資等屬性,像這樣個人隱私的屬性是不想讓其它人隨意就能獲得到的,如果你不使用封裝,那麼別人想知道就能得到,但是如果你封裝上之後別人就沒有辦法獲得封裝的屬性,除非你自己把它說出去,否則別人沒有辦法得到。

再比如說,個人電腦都有一個密碼,不想讓其它人隨意的登陸,在你的電腦裡面拷貝和粘貼。還有就是像人這個對象,身高和年齡的屬性,只能是自己來增漲,不可以讓別人隨意的賦值等等。

使用private這個關鍵字來對屬性和方法進行封裝:

原來的成員:var $name;   //聲明人的姓名var $sex;    //聲明人的性別var $age;    //聲明人的年齡function run(){…….}改成封裝的形式:private $name;          //把人的姓名使用private關鍵字進行封裝private $sex;      //把人的性別使用private關鍵字進行封裝private $age;      //把人的年齡使用private關鍵字進行封裝  private function run(){……}  //把人的走路方法使用private關鍵字進行封裝注意:只要是成員屬性前面有其它的關鍵字就要去掉原有的關鍵字“var”。

通過private就可以把人的成員(成員屬性和成員方法)封裝上了。封裝上的成員就不能被類外面直接存取了,只有對象內部自己可以訪問;

私人的成員是不能被外部存取的, 因為私人成員只能在本對象內部自己訪問,比如,$p1這個對象自己想把他的私人屬性說出去,在say()這個方法裡面訪問了私人屬性,這樣是可以。(沒有加任何存取控制,預設的是public的,任何地方都可以訪問)

因為構造方法是預設的公有方法(構造方法不要設定成私人的),所以在類的外面可以訪問到,這樣就可以使用構造方法建立對象, 另外構造方法也是類裡面的函數,所以可以用構造方法給私人的屬性賦初值。Say()的方法是預設公有的, 所以在外面也可以訪問的到, 說出他自己的私人屬性。

從上面的例子中我們可以看到,私人的成員只能在類的內部使用,不能被類外部直接來存取,但是在類的內部是有許可權訪問的,所以有時候我們需要在類的外面給私人屬性賦值和讀取出來,也就是給類的外部提供一些可以存取的介面,上例中構造方法就是一種賦值的形式,但是構造方法只是在建立對象的時候賦值,如果我們已經有一個存在的對象了,想對這個存在的對象賦值,這個時候,如果你還使用構造方法傳值的形式傳值,那麼就建立了一個新的對象,並不是這個已存在的對象了。所以我們要對私人的屬性做一些可以被外部存取的介面,目的就是可以在對象存在的情況下,改變和存取屬性的值,但要注意,只有需要讓外部改變的屬性才這樣做,不想讓外面訪問的屬性是不做這樣的介面的,這樣就能達到封裝的目的,所有的功能都是對象自己來完成,給外面提供盡量少的操作。

http://www.bkjia.com/PHPjc/752520.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/752520.htmlTechArticle物件導向的概念 物件導向編程(Object Oriented Programming, OOP, 物件導向程式設計)是一種電腦編程架構,OOP的一條基本原則是電腦程式是...

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.