PHP-面向對象編程
1 面向對象(OO):
面向對象:
將要處理的問題抽象為對象,然后通過對象的屬性和行為來解決對象的實際問題
三大特性:封裝,繼承,多態
面向過程和面向對象區別:
面向過程:最小單位是函數
面向對象:最小單位是對象
類:是具有相同屬性和方法的集合,是一個獨立的程序單位
對象:是類實例化之后的產物
類和對象的關系:
類的實例化結果就是對象,對象的抽象就是類
類就是一組具有(特征)成員屬性和相同(相同)成員方法的對象
2 抽象一個類
類的聲明
[權限修飾符] class 類名{
[public $property =[value...]]//屬性
[function functionname(args)
//代碼
]//類的方法
}
類名和變量名的明命名規則相似,如果有多個單詞組成,習慣上每個單詞的首字母大寫,而且要有意義
成員屬性:為靜態描述,可以使用php中的標量類型和符合類型
格式: public 屬性名稱
也可以采用private 等,當不確定的用那個的時候,使用public或者var(php4)
權限修飾符號默認采用:public
成員方法:為動態描述
格式:
[權限修飾符] function 方法名(args){
//代碼
}
3 實例化對象
創建對象:
$對象名稱= new 類名稱([參數]);
實例化多個對象,各對象之間都是獨立的,存放在不同的內存空間
如果對象創建時,沒有手動的設置構造方法,則系統自動創建一個不帶參數的默認構造函數
對象類型在內存中的分配:
邏輯內存: 棧空間段 堆空間段 初始化數據段 代碼段
棧空間段
特點是:先進先出
空間小,cpu訪問速度快,存放程序中臨時創建的變量,占用空間不大并且長度不變的,[整型,浮點型...]
堆空間段:
程序運行中,被動態分配的的內存段,大小不固定,存儲詩句長度可變或占用內存較大的數據
[字符串,數組,對象]
初始化數據段:
存儲可執行文件中已初始化的全局變量[程序靜態分配的變量]
代碼段:
可執行文件的操作指令,是可執行文件在內存中的鏡像
對象類型在內存存儲方式
例如:
class person{
public $name;
public $age;
public $sex;
function eat(){}
function run(){}
}
$person=new person();
等式右邊為堆內存,存放對象實例
左邊為棧內存,存放對象引用
1 當new person()的時候,計算機在堆內存就為我們創建的對象開辟一個新的空間,存儲對象實例
|--$name;
|--$age;
new person() |--$sex;
|--eat();
|--run();
每個對象都有一個十六進制的內存地址,例如:0x001
2 對象中的eat(),run()方法的存放在可執行代碼段中,堆內存中的每個都可以引用.
function eat(){}
function run(){}......
3 當創建的對象賦值給$person時,就將對象的十六進制地址存放在了棧內存,并形成一個指針指向堆內存的對象,
形成了一個對象的引用,通過對象的引用類訪問對象
對象中成員的訪問:
使用:"->"符號
對象引用名->成員屬性/成員方法
例如:$person->name;
特殊的對象引用:$this
屬于對象級別,創建了那個對象,$this就代表那個對象,在類的成員方法中使用,具體代表了實例化的對象操作
構造方法和析構方法
構造方法:
php4:名稱必須和類名相同
php5:使用魔術方法關鍵詞:__construct
Function __construct([參數]){}
觸發時機:創建一個對象的時候自動調用執行
作用:可以在創建對象的實現對象初始化
析構方法:
Function __destruct(){}
觸發時機:在銷毀一個對象的時候自動調用執行(php5新特性)
作用:釋放資源,關閉連接,做一些清理工作等
注:對象的引用存放在棧內存,其特點是先進先出,所以后創建的對象先銷毀.
4 封裝性
特點:
1 把對象的全部成員方法和成員方法結合在一起,形成一個不可分割的獨立單位
2 信息屏蔽,盡可能的隱藏內部細節,對外形成一個邊界只保留有限的對外接口
設置私有成員:
使用關鍵字"private"修飾
private的訪問權限:
在類的外部不能夠訪問
在類的內部可以訪問
子類中不可以訪問
如果沒有設置訪問權限:默認為public
魔術方法:php中把兩個(__)開頭的類方法叫做魔術方法.
__consturct() / __destruct() / __call() / __set()
__get() / __clone() / __isset() / __unset() / __sleep() / __wakeup()
__set()
Function __set($proName,$proValue){
$this->$proName=$proValue;
}
觸發時機:在類的外部設置類的私有屬性成員值的時候自動調用
特點:1需要兩個參數(屬性的名稱,設置的屬性的值)
2可以在屬性的方法前面加上private關鍵詞修飾,在5.3以上版本中加上private修飾,會出現警告
__get()
Function __set($proName){
Return $proName;
}
觸發時機:在類的外部獲取類的私有屬性成員的時候自動調用
特點:1 需要一個參數,就是獲取私有成員屬性的屬性名
__isset()
Function __isset($proName){
Isset($proName);
}
觸發時機:在類的外面isset()或者empty()檢測類的私有成員屬性是否設置時自動調用
特點: 1 需要一個參數,檢測私有屬性的屬性名
__unset()
Function __unset($proName){
Isset($proName);
}
觸發時機:在類的外面unset()有成員屬性的時候自動調用
特點:1 需要一個參數,刪除私有屬性的屬性名
5 繼承性
特點:
1 使所建立的軟件具有開放性,可擴充性
2 增加了代碼的可重用性,簡化了類和對象創建的工作量
3 增加類軟件的可維護性,通過繼承,使公用的特性得到共享,擴展和延伸
4 php中繼承為單繼承,用子類擴展父類
類繼承的應用
1 聲明一個子類,使用extends關鍵字去繼承擴展一個父類
2 子類可以繼承父類的所有內容,包括成員屬性,成員方法,構造方法
3 可以在子類中使用"$this->"來調用繼承父類過來的內容
對類成員的訪問控制
Public:公用的
類內部:可以訪問
類外部:可以訪問
子類中:可以訪問
Protected:受保護的
類內部:可以訪問
類外部:不可以訪問
子類中:可以訪問
Private:私有的
類內部:可以訪問
類外部:不可以訪問
子類中:不可以訪問
子類中重載父類的方法
1 子類可以聲明和父類相同的方法名,即子類覆蓋了父類中同名的方法
2 子類中調用父類中方法
對象->成員方法名:子類調用父類繼承過來的方法
parent::成員方法名:子類調用覆蓋的父類方法
3 子類中編寫構造方法,如果父類中也有構造方法一定要去調用一次父類中被覆蓋的構造方法
4 父類和子類都存在構造方法,系統會調用子類的方法
5 子類重載父類的方法,則方法的權限等級不能低于父類(子類可以訪大權限,但不能縮小權限)
6 常見的關鍵字和魔術方法
final關鍵字:
Final class Demo{
Final function add();
Final function del();
}
1 final不能修飾成員屬性
2 final只能修飾類和方法
作用:
1 使用final修飾的類,不能被繼承
2 使用final修飾的方法不能被子類重載覆蓋
static關鍵字:
Class Demo{
Static const USER;
Static function fun1(){}
}
1 static只能修飾成員屬性和成員方法,不可以修飾類
2 用static修飾的成員屬性,可以被同一個類所以對象共享,屬于類級別
3 靜態的數據存在內存中的靜態數據段里,節約資源,提高效率
4 靜態的數據在類第一次加載時分配到內存里,以后用到類時則直接調用
第一次加載:指的是第一次使用時例如$person->say(),Person::say()...
5 訪問類中static修飾的成員屬性和成員方法,類不需要聲明,不需要創建對象
6 靜態成員屬性不能通過$this去訪問
7 static和private等權限修飾關鍵字可以同時存在,效果疊加
8 靜態方法中不能包含非靜態的成員,在非靜態的方法中可以包含靜態成員
9 在靜態成員方法中不能出現$this關鍵字 ,但是可以在靜態成員方法內部使用$this調用靜態成員方法
10 靜態成員方法的訪問
訪問方式:
在類中:
類名::成員方法
self::成員方法(self為類級別)
類外部:
類名::類中成員
對象名稱->成員方法
11 靜態數據的訪問速度較快,所以在不影響結構的情況下,盡量將成員屬性和對象設置為靜態的
Const
Class Demo{
Static const USER;
Static function fun1(){}
}
1 只能修飾成員屬性
2 類中聲明成員屬性常量使用const關鍵字
3 常量通常使用大寫(命名方式和define是一樣的)
4 常量只能是標量,前面沒有$符號
5 常量一定要在聲明時給初值,在程序運行的過程中常量的值是不可以改變的
6 常量的訪問方式,不能用$this->訪問:
7 常量的訪問:
在類中:
類名::常量
self:常量
類外部:
類名::常量(不需要實例化)
__clone()
1 當對象賦值給另一個對象的時候,則為引用關系
$p=new Person();
$p1=$p;
2 對象克隆(clone Oject)的時候,用clone關鍵字
當$p1=clone $p;時
Function __clone(){
//$this:代表克隆的對象,可以進行初始化操作
}
注:
對象的引用,為一個對象多個名稱,內存中指針指向同一個地址
對象的克隆,復制一個新的對象,相當于創建了一個新的對象
觸發時機:在克隆對象的時候自動調用
作用:在克隆的復本對象中進行初始化設置,在__clone()方法中$this表示復本對象
特點:不需要參數
復本的對象$this,該方法類似__construct()
__toString()
Function __toString(){
Return "需要輸出的字符串";
}
觸發時機:當echo一個對象的時候,系統自動調用__toString()方法
特點:該方法必須return一個字符串
__call()
Function __call($proName,$proValue){
//$proName:指的是調用的方法名
//$proValue:指的是有參數組成的數組
}
觸發時機:當調用一個不存在的方法時,系統自動調用
作用:處理不存在方法的錯誤調用
特點:__call()需要兩個參數,第一個調用的方法名,第二個為參數組成的數組
__autoload()
Function __autoload($className){
Include $className.'.class.php';
}
注意:該魔術方法是唯一一個不再類中的方法
觸發時機:只要在頁面中使用到類的時候該方法自動執行,去尋找該類
并將該類的類名自動傳遞給__autoload()方法的參數
特點:只用一個參數,當使用那個類的時候,該方法自動執行尋找相應的類,并將類名賦值給參數
作用:自動加載所需的類
使用到類例如:
$p->say();
Person::test();...
對象串行化
1 串行化就是把整個對象轉化為二進制字符串
2 串行化應用:
1 對象需要在網絡中傳輸時,將對象串行化成二進制串后在網絡中傳輸
2 對象需要持久保存時,將對象串行化之后寫入文件或數據庫
3 串行化方法:
串行化:serialize()參數是一個對象,返回串行化后的二進制串
反串行化:unserialize()參數是對象的二進制串,返回新生成的對象
__sleep()
$p=new Person('張三',23,'女');
$str=serialize($p);
File_put_contents('mess.txt',$str);
Function __sleep(){
Return array();//array中輸入需要進行序列化的成員
}
觸發時機:在序列化時自動調用
作用:將一個對象的部分成員屬性或者功能進行串行化
只要這個方法返回一個數組,數組中的值為對象成員要序列化的名稱
如果不使用這個方法,則整個對象進行序列化
__wakeup()
$p=unseralize(file_get_contents('mess.txt'));
Function __wakeup(){
//$this代表序列化的對象
}
觸發時機:在對象反序列化的時候自動調用執行
作用:對反序列化后的對象進行初始化工作
類似此類的方法有:__construct(初始化參數),__clone(不需要參數),__wakeup()
7 抽象類和接口
注:抽象類是一種特殊的類,接口是一種特殊的抽象類
抽象類:
抽象方法:沒有方法體的方法就是抽象方法,例如 function test();
抽象類:含有抽象方法的類就是抽象類
1 抽象方法必須用abstract修飾
2 如果一個類含有抽象方法,這個類就是抽象類,必須用abstract修飾
3 抽象類中可以有非抽象方法,在抽象類中可以包含多個抽象方法
4 抽象類可以聲明屬性和常量
5 抽象方法關鍵字和權限修飾關鍵字可以同時存在private abstract function test();效果疊加
6 抽象類不能夠被實例化,不能夠創建抽象類的對象
7 抽象類必須只能通過繼承來實現
8 繼承抽象類的子類必須實現抽象類的所有方法
9 子類實現抽象方法時,抽象方法的參數和默認值必須保持一致
10 抽象方法之間是可以繼承的,必須按照規范來實現功能
接口技術
1 接口中所有方法均為抽象方法
2 不能在接口中聲明變量,只能用const修飾的常量
3 接口中的所有成員必須都是public權限等級
4 接口的聲明不能用abstract修飾,而是用interface關鍵字
5 實現接口不能用extends,而是用implements關鍵字
6 在實現接口的子類中,接口的所有方法都要實現,方法的形參,默認值都需要保持一致
7 子類可以實現多個接口,各個接口使用逗號隔開
implements interfaceName1,interfaceName2.....{}
8 子類在實現接口的同時還可以繼承抽象類和普通類,
9 抽象類客普通類的實現使用implments關鍵字,而接口實現接口使用關鍵字extends
10 接口不能被實例化,需要子類去實現
11 接口中不能聲明變量,只能聲明常量
抽象類和接口的比較:
1 作用相同,不能創建對象,都需要子類去實現
2 接口的聲明和抽象類不一樣,接口interface,抽象列abstract
3 使用一個類實現接口,用implements,不用extends,抽象類用extends
4 接口中所有的成員方法必須都是抽象方法,不用abstract修飾
5 接口中的成員屬性只能聲明常量,不能聲明變量,
6 接口類的訪問權限必須是public,抽象列最低可以是protected
8 多態性
多態
php中的多態性指的是方法重寫,指的是一個子類可以重新修改父類中的方法,使其具有自己的特征
多態可以通過聲明抽象類和接口來實現