首頁  >  文章  >  後端開發  >  詳解我對PHP中物件導向的認識

詳解我對PHP中物件導向的認識

零下一度
零下一度原創
2017-07-03 09:33:481454瀏覽

前言: 

#    今天來跟大家介紹PHP的物件導向。說到面向對象,我不得不提一下面向過程,因為本人在初學時,常常分不清楚。 那麼物件導向和流程導向有什麼差別呢?以下跟大家簡單介紹一下:

物件導向#專注於由哪個物件來處理一個問題。

其最大特點是由一個一個具有屬性和功能的類,從類別中拿到對象,進而處理問題。  

以過程專注於解決一個問題的流程。 其最大特點是由一個一個的函數去解決處理這個問題的一系列過程。  

 

了解了物件導向與流程導向的差異之後,我們來學習有關PHP的物件導向的基礎知識。

***本章關鍵字:物件導向基礎、封裝與繼承、PHP關鍵字、單例、物件串列化和魔術方法、抽象類別和抽象方法、介面與多態。

 

 

 

#################################################### ####你需要知道的~~~我們要知道的PHP物件導向有三大特點:繼承;封裝;多態性。 ######### #########################一、物件導向基礎#####################一、物件導向基礎############ ##########

 

物件導向

 


 

1、什麼是類別?
具有相同屬性(特徵)和方法(行為)的一系列個體的集合,類別是抽象的概念。

2、什麼是物件?

從類別中,得到的具有具體屬性值的個體,稱為物件。對像是一個具體的個體。
eg:人類;張三

3、類別和物件的關係?

類別是物件的抽象化!對像是類別的具體化!

類別只是表示這類物件有哪些屬性,但是不能有具體的值,所以類別是抽象的。
物件是將類別的所有屬性賦值後,產生具體的個體,所有物件是具體的。

二、類別的宣告與實例化
1、如何宣告一個類別:
class 類別名稱{

存取修飾符  $屬性[=預設值];

[存取修飾符] function 方法(){}
## }
#2、宣告一個類別的注意事項:
  ①類別名稱只能有字母數字底線組成,開頭不能是數字,必須符合大駝峰法則;

  ②類別名稱必須使用class修飾,類別名稱後面一定不能有();
  ③屬性必須要帶存取修飾符,方法可以不帶訪問修飾符。

3、實例化物件及物件屬性方法的呼叫:
#$物件名稱 = new 類別名稱(); //()可以不帶

類別外部呼叫屬性與方法:
$物件名稱-> $屬性名稱; //使用->呼叫屬性時,屬性名不能帶$符號

類別內部呼叫屬性與方法:
$this -> $屬性名稱;
三、建構子

1、什麼是建構子?
建構子是類別中的一個特殊函數,當我們使用new關鍵字實例化物件時,相當於呼叫了類別的建構子。

######2、建構子有什麼作用? #########實例化物件時,自動調用,用於給物件的屬性賦初值! ######

3、建構子的寫法:
①建構函式名,必須與類別同名
[public] function Person($name){
$this -> name = $name;
}
②使用魔術方法__construct
#[public] function __construct($name){
$this -> name = $name;
}
4、建構函式註意事項:
①第一種寫法,建構函式名稱必須與類別同名! ! ! !
②如果一個類別沒有手寫建構函數,則系統預設會有一個空參構造,因此可以使用new Person();
如果我們寫了帶參數的建構函數,則不會再有空參構造,也就是不能直接使用new Person();
Person後面的()中的參數列表,必須符合建構子的要求! ! ! !
③如果兩種建構子同時存在,將使用__construct。

5、析構函數:__destruct():
#①析構函數在物件被銷毀釋放之前自動呼叫;
②析構函數不能帶有任何的參數;
③析構函數常用於物件使用完以後,釋放資源,關閉資源等。

6、魔術方法:
PHP中,給我們一系列用__開頭的函數,這些函數不需要自己手動調用,
會在適當的時機自動調用,這類函數稱為魔術稱為魔術函數。
eg:function __construct(){} 在類別new一個物件時自動呼叫
  function __destruct(){} 在物件被銷毀時自動呼叫
我們要求,除了魔術方法之外,自訂的函數與方法不能使用__開頭。

最後,一般對於功能比較複雜的類,我們會單獨的寫到一個類別文件中。
類別檔案的命名,同一小寫,使用"類別名稱小寫.class.php"的方式命名。
在其他檔案中使用這個類別時,可以使用include導入這個".class.php"檔案。

 

 

#二、封裝與繼承
#

 

1、什麼是封裝?
透過存取修飾符,將類別中不需要外部存取的屬性和方法進行私有化處理,以實現存取控制。

*注意:是實現存取控制,而不是拒絕存取。也就是說,我們私有化屬性後,需要提供對應的方法,讓使用者透過我們提供的方法處理屬性。

2、封裝的作用?
①使用者只關心類別能夠提供的功能,不關心功能實現的細節! (封裝方法)
②對使用者的資料進行控制,防止設定不合法數據,控制傳回給使用者的資料(屬性封裝+set/get方法)

3、實作封裝操作?
①方法的封裝
對於一些只在類別內部使用的方法,而不是像對外部提供使用,那麼,這樣的方法我們可以使用private進行私有化處理。
private function formatName(){} //這個方法只要能在類別內部使用$this呼叫
function showName(){
# $this -> formatName();
}
#②屬性的封裝+set/get方法
為了控制屬性的設定以及讀取,可以將屬性進行私有化處理,並要求使用者透過我們提供的set/get方法進行設定
#private $age;
function setAge($age){
$this->age=$age;
}
function getAge(){
return $this->age;
}
#$物件->getAge();
$物件->setAge(12);

③屬性的封裝+魔術方法
private $age;
function __get($key){
return $this->$key;
}
function __set($key,$value){
$this->$key=$value;
}
$對象->age; //存取物件私有屬性時,自動呼叫__get()魔術方法,並且將存取的屬性名稱傳給__get()方法;
$物件-> age=12; //設定物件私有屬性時,自動呼叫__set()魔術方法,並且將設定的屬性名稱以及屬性值傳給__set()方法;

注意:在魔術方法中,可以使用分支結構,判斷$key的不同,進行不同操作。

4、關於封裝的魔術方法:
①__set($key,$value):給類別私有屬性賦值時自動調用,呼叫時會傳遞兩個參數給方法:需要設定的屬性名,屬性值。
②__get($key,$value):讀取類別私有屬性時自動調用,呼叫時給方法傳遞一個參數,需要讀取的屬性名稱;
③__isset($key):外部使用isset()函數偵測私有屬性時,自動呼叫。
>>>類別外部使用isset();偵測私有屬性,預設是偵測不到的。 false
>>>所以,我們可以使用__isset();函數,在自動呼叫時,回傳內部偵測結果。
function __isset($key){
return isset($this -> $key);
##}
當外部使用isset($物件名稱->私有屬性);偵測時,將自動呼叫上述__isset()傳回的結果!

④__unset($key):外部使用unset()函數刪除私有屬性時,自動呼叫;
function __unset($key){
unset($this -> $key);
}
當外部使用unset($物件名稱->私有屬性);刪除屬性時,自動將屬性名稱傳給__unset(),並交由這個魔術方法處理。


【繼承的基礎】
1、如何實作繼承?
給子類別使用extends關鍵字,讓子類別繼承父類別;
#class Student extends Person{}








# 2、實作繼承的注意事項?
①子類別只能繼承父類別的非私有屬性。
②子類別繼承父類別後,相當於將父類別的屬性和方法copy到子類,可以直接使用$this呼叫。

③PHP只能單繼承,不支援一個類別繼承多個類別。但是一個類別進行多層繼承。
class Person{}

class Adult extends Person{}

class Student extends Adult{}

#//Student 類別同時具有了Adult類別和Person類別的屬性和方法

#3、方法覆寫(方法重寫)

條件一:子類別繼承父類別
條件二:子類別重寫父類別已有方法

#符合上述兩個條件,稱為方法覆寫。覆寫之後,子類別呼叫方法,將呼叫子類別自己的方法。

同樣,除了方法覆蓋,子類別也可以具有與父類別同名的屬性,進行屬性覆蓋。

######如果,子類別重寫了父類別方法,如何在子類別中呼叫父類別同名方法? ############partent::方法名稱();######### 所以,當子類別繼承父類別時,需在子類別的建構中的第一步,首先呼叫父類別構造進行複製。 ############function __construct($name,$sex,$school){#########partent::__construct($name,$sex);#### #####$this -> school = $school;#########}######### ###
三、PHP關鍵字

 

1、final
①final修飾類,此類為最終類,不能被繼承!
②final修飾方法,此方法為最終方法,不能被重寫!
③final不能修飾屬性。

2、static
①可以修飾屬性和方法,分別稱為靜態屬性和靜態方法,也叫類別屬性,類別方法;
②靜態屬性,靜態方法,只能使用類別名稱直接呼叫。
使用"類別名稱::$靜態屬性" , "類別名稱::靜態方法()"
Person::$sex;   Person::say( );
③靜態屬性和方法,在類別裝載時就會聲明,先於物件產生。
④靜態方法中,不能呼叫非靜態屬性或方法;
#非靜態方法,可以呼叫靜態屬性和方法。
(因為靜態屬性和方法在類別裝載時已經產生,而非靜態的屬性方法,此時還沒有實例化誕生)
⑤在類別中,可以使用self關鍵字,代指本類名。
class Person{
## static $sex = "nan";
function say(){
echo self::$sex;
}
}
⑥靜態屬性是共享的,也就是new出很多對象,也是共用一個屬性。

3、const關鍵字:
在類別中宣告常數,不能是define()函數!必須使用const關鍵字。
與define()宣告相似,const關鍵字宣告常數不能帶$,必須全部大寫!
常數一旦聲明,就不能改變。呼叫時與static一樣,使用類別名稱呼叫Person::常數。

4、instanceof運算子:
偵測一個對象,是否是某一個類別的實例。 (包括爸輩,爺爺輩,太爺爺輩…)
$zhangsan instanceof Person;

【小總結】幾種特殊操作符
1、 . 只能連接字串; "".""
#2、 => 宣告陣列時,關聯鍵與值["key"=> ;"value"]
3、 -> 物件($this new出的物件)呼叫成員屬性,成員方法;
4、::
①使用parent關鍵字,呼叫父類別中的同名方法:parent::say();
②使用類別名稱(和self)呼叫類別中的靜態屬性,靜態方法,以及常數。

 

##

 

單例模式也稱為單態模式。
可以保證,一個類別只能有一個物件實例。

實作重點:
①建構子私有化,不允許使用new關鍵字建立物件。
②對外提供取得物件的方法,在方法中判斷物件是否為空。
如果為空,則建立物件並傳回;如果不為空則直接傳回。
③實例物件的屬性以及取得物件的方法必須都是靜態的。
④之後,建立物件只能使用我們提供的靜態方法。
eg:$s1 = Singleton::getSingle();

#四、單例
五、物件串列化和魔術方法

 

***關鍵字:clone與__clone、__antoload()、串列化與反序列化(序列化與反序列化)、型別限制、魔術方法小總結(12個)


一、clone與__clone
1、當使用=講一個對象,賦值給另一個對象時,賦的實際是物件的位址。
兩個物件指向同一位址,所以一個物件改變,另一個也會改變。
eg: $lisi = $zhangsan;
2、如果想要將一個物件完全克隆出另一個對象,兩個物件是獨立的,互不幹擾的,
則需要使用clone關鍵字;
eg: $lisi = clone $zhangsan; //兩個物件互不干擾
3、__clone():
①當使用clone關鍵字,複製物件時,自動呼叫clone函數。
②__clone()函數,類似於克隆時使用的建構函數,可以給新克隆物件賦初值。
③__clone()函數裡面的$this指的是新克隆的對象
某些版本中,可以用$that代指被克隆對象,絕大多數版本不支援。
4、__toString()
當使用echo等輸出語句,直接列印物件時呼叫echo $zhangsan;
##那麼,可以指定__toString()函數傳回的字串;
function __toString(){
return "haha";
# }
echo $zhangsan; //結果為:haha

#5、__call()
呼叫類別中未定義或未公開的方法時,會自動執行__call()方法。
在自動執行時,會給__call()方法傳遞兩個參數;
參數一:呼叫的方法名稱
參數二:(陣列)呼叫方法的參數清單。

二、__antoload()
①這是唯一一個不在類別中使用的魔術方法;
②當當實例化一個不存在的類別時,自動呼叫這個魔術方法;
③呼叫時,會自動給__autoload()一個參數:實例化的類別名稱
# 所以可以使用這個方法實現自動載入檔案的功能。
function __autoload($className){
#include "class/".strtolower($className).".class.php";
}
$zhangsan=new Person();//本檔案內沒有Person類,會自動執行__autoload()載入person.class.php檔案#

三、串列化與反串列化(序列化與反序列化)
#1、序列化:將物件經過一系列操作,轉換為一個字元串的過程,稱為串列化;
(物件透過寫出描述自己狀態的數值來記錄自己)
2、反串列化:將串行化後的字串,再轉為物件的過程,稱為反串行化;
3、何時使用串行化?
①物件需要在網路中傳輸的時候
② 物件需要在檔案或資料庫中持久保存的時候
4、如何實現串行化與反串行化
串行化:  $str=serialize($zhangsan);
反串行化:$duixiang=unserialize ($str);
5、__sleep()魔術方法:
①當執行物件串列化的時候,會自動執行__sleep()函數;
②__sleep()函數要求回傳一個數組,數組中的值,就是可以串行化的屬性;不在數組中的屬性,不能被串行化;
#function __sleep(){
return array("name","age"); //只有name/age兩個屬性可以串列化。
}

6、__wakeup()魔術方法
①當反串列化物件時,自動呼叫_ _wakeup()方法;
②自動呼叫時,用於給反串行化產生的新物件屬性,進行重新賦值。
function __wakeup(){
$this -> name = "李四";
}

#四、型別限制
1、型別約束:是指在變數時,加上資料類型,用來約束此變數只能存放對應的資料型別。
(這個運算常見於強型別語言,在PHP中,只能實作陣列與物件的型別限制)
2、如果型別約束為某一個類,則本類以及本類的子類對象,都可以通過。
3、在PHP中,型別約束,只能發生在函數的形參中。
class Person{}
class Student extends Person{}
function func(Person $p){ //約束函數的形參,只接受Person類別及Person子類別
echo "1111";
echo $p -> name;



}
func(new Person()); √

###func(new Student()); √#########func(" 111"); ×############形如new Person();的形式,我們稱為"匿名物件";############※※ ※基底類別:父類別    #########※※※衍生類別:子類別######

五、魔術方法小總結
1、__construct():建構函數,new一個物件時,自動呼叫。
2、__destruct():析構函數,當一個物件被銷毀前,自動呼叫。
3、__get():存取類別中私有屬性時,自動呼叫。傳遞讀取的屬性名,傳回$this->屬性名
4、__set():給類別的私有屬性賦值時,自動呼叫。傳遞需要設定的屬性名稱和屬性值;
5、__isset():使用isset()偵測物件私有屬性時,自動呼叫。傳遞偵測的屬性名,傳回isset($this -> 屬性名);
#6、__unset():使用unset()刪除物件私有屬性時,自動呼叫。傳遞刪除的屬性名,方法中執行unset($this -> 屬性名);
#7、__toString():使用echo列印物件時,自動呼叫。返回想要在列印物件時,顯示的內容;返回必須是字串;
8、__call():呼叫一個類別中未定義或未公開的方法時,自動呼叫。傳遞被呼叫的函數名,和參數列表數組;
9、__clone():當使用clone關鍵字,複製一個物件時,自動呼叫。作用是為新複製的物件初始化賦值;
10、__sleep():物件序列化時,自動呼叫。傳回一個數組,數組中的值就是可以序列化的屬性;
11、__wakeup():物件反序列化時,自動呼叫。為反序列化新產生的對象,進行初始化賦值;
12、__autoload():需要在類別外部宣告函數。當實例化一個未聲明的類別時,自動呼叫。傳遞實例化的類別名,可以使用類別名稱自動載入對應的類別檔案。

 

#六、抽象類別與抽象方法
#

 

1、什麼是抽象方法?
沒有方法體{}的方法,必須使用abstract關鍵字修飾。這樣的方法,我們稱為抽象方法。
abstract function say(); //抽象方法

#2、什麼是抽象類別?
使用abstract關鍵字修飾的類別就是抽象類別。
abstract class Person{}

3、抽象類別的注意事項:
① 抽象類別可以包含非抽象方法;
② 包含抽象方法的類別必須是抽象類,抽象類別不一定必須包含抽象方法;
③ 抽象類,不能實例化。 (抽象類別中可能包含抽象方法,抽象方法沒有方法體,實例化呼叫沒有意義)
我們使用抽象類別的目的,就是限制實例化! ! !

4、子類別繼承抽象類,那麼子類別必須重寫父類別的所有抽象方法,除非,子類別也是抽象類別。

5、使用抽象類別的作用?
① 限制實例化。 (抽象類別是不完整的類,裡面的抽象方法沒有方法體,所以不能實例化)
② 抽象類別為子類別的繼承提供一個規範,子類別繼承一個抽象類,則必須包含並且實作抽象類別中已定的抽象方法。

 

#七、介面與多態

 

一、介面
1、什麼是介面?
介面是一種規範,提供了一組實作介面的類別所必須實現的方法組合。
介面使用interface關鍵字宣告;
interface Inter{}

2、介面中的所有方法,必須都是抽象方法。
介面中的抽象方法不需要也不能使用abstract修飾。

3、介面中​​不能宣告變量,不能有屬性,只能使用常數! ! !

4、介面可以繼承接口,使用extends關鍵字!
介面使用extends繼承接口,可以實現多重繼承。
interface int1 extends Inter,Inter2{}

#5、類別可以實作接口,使用implements關鍵字!
類別使用implements實作接口,可同時實作多個接口,多個接口間逗號分隔;
abstract class Person implements Inter,Inter2{}
#一個類別實作一個或多個接口,那麼這個類,必須實作所有接口中的所有抽象方法!
除非,這個類別是抽象類別。

※【介面&&抽象類別區別】
#1、宣告方式上,介面使用interface關鍵字,抽象類別使用abstract class。
2、實作/繼承方式上,一個類別使用extends繼承抽象類,使用implements實作介面。
3、抽象類別只能單繼承,介面可以多實作。 (介面extends介面)、多重實作(類別implements介面)
4、抽象類別中可以有非抽象方法,介面中只能有抽象方法,不能有費抽象方法。
抽象類別中的抽象方法必須使用abstract關鍵字修飾,介面中抽象方法不能帶修飾字。
5、抽象類別是個類,可以有屬性、變數;介面中只能有常數。

二、多態
1、一個類,被多個子類繼承。
如果,這個類別的某個方法,在多個子類別中,表現出不同的功能,我們稱這種行為為多態。

2、實作多態的必要途徑:
① 子類別繼承父類別;
② 子類別重寫父類別方法;
③ 父類別引用指向子類別物件


 

#########################################################################################################################################

以上是詳解我對PHP中物件導向的認識的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn