OOP是什么?
OOP是面向對象編程,面向對象編程是一種計算機編程架構。
OOP的基本原則是計算機程序是由單個能起到子程序作用的單元或對象組合而成。
基本概念:
類:定義了事務的抽象特點。包含了數據的形式以及數據的操作。class 定義類。
對象:類的實例。new 運算符類實例化為對象。
成員變量:定義在類內的變量。類實例化為對象后,該變量稱為對象的屬性。
成員函數:定義在類內的方法。
重載:函數或者方法有同樣的名稱,但是參數列表不相同的情形。
什么是構造函數,什么是析構函數,作用是什么?
構造函數
構造函數(方法)是對象創建完成后第一個被對象自動調用的方法。
它存在于每個聲明的類中,是一個特殊的成員方法。
作用是執行一些初始化的任務。 PHP中使用 __construct() 聲明構造方法,并且只能聲明一個。
析構函數
析構函數(方法)作用和構造方法正好相反,是對象被銷毀之前最后一個被對象自動調用的方法。
是PHP5中添加的內容,作用是用于實現在銷毀一個對象之前執行一些特定的操作;
諸如關閉文件和釋放內存等。 使用__destruct()聲明析構函數。
什么是魔術方法?
魔術方法時系統提供的,我們直接使用即可。
所有的魔術方法都是以 __ (兩個下劃線)開頭的。
魔術方法是在滿足某個條件時,由系統自動調用的
魔術方法有哪些?
__construct() 構造函數
__destruct() 析構函數
__sleep() 串行化/序列化的時候用
__wakeup() 反串行化/反序列化的時候用
__toString() 將一個對象當做字符串來輸出時調用
__clone() 克隆對象時被調用
__autoload() 實例化一個對象時,如果對應的類不存在,則該方法被調用
__call() 調用方法,若方法存在、則直接調用;若不存在,則調用__call() 函數
__set() 設置對象屬性,若屬性存在、則直接賦值;若不存在、則調用__set()函數
__get() 獲取對象屬性,若屬性存在、則直接返回;若不存在、則調用__get()函數
__iseet() 檢測一個對象的屬性是否存在時被調
__unset() 清除一個對象的屬性時被調用
封裝性
就是將一個類的使用和實現分開, 只保留部分接口和方法與外部聯系,或者說只公開了一些供開發人員使用的方法。于是開發人員只需要關注這個類如何使用,而不用去關心其具體的實現過程,這樣就能實現MVC分工合作,也能有效避免程序間相互依賴,實現代碼模塊間松藕合。
繼承性
就是子類自動繼承其父級類中的屬性和方法,并可以添加新的屬性和方法或者對部分屬性和方法進行重寫。繼承增加了代碼的可重用性。PHP只支持單繼承,也就是說一個子類只能有一個父類。
多態性
子類繼承了來自父級類中的屬性和方法,并對其中部分方法進行重寫。于是多個子類中雖然都具有同一個方法,但是這些子類實例化的對象調用這些相同的方法后卻可以獲得完全不同的結果,這種技術就是多態性。多態性增強了軟件的靈活性。
OOP的優點有哪些?
易維護
采用面向對象思想設計的結構,可讀性高,由于繼承的存在,即使改變需求,那么維護也只是在局部模塊,所以維護起來是非常方便和較低成本的。
質量高
在設計時,可重用現有的,在以前的項目的領域中已被測試過的類使系統滿足業務需求并具有較高的質量。
效率高
在軟件開發時,根據設計的需要對現實世界的事物進行抽象,產生類。使用這樣的方法解決問題,接近于日常生活和自然的思考方式,勢必提高軟件開發的效率和質量。
易擴展
由于繼承、封裝、多態的特性,自然設計出高內聚、低耦合的系統結構,使得系統更靈活、更容易擴展,而且成本較低。
方法重寫
// 如果從父類繼承的方法不能滿足子類的需求,可以對其進行改寫; // 這個過程叫方法的覆蓋(override),也稱為方法的重寫。 // 實例中重寫了 getUrl 方法: /***** 原來的 ****/ class p { var $url; var $title function getUrl() { echo $this->url; } } /***** 繼承后重寫 ****/ class s extends p { var $url; var $ti tle function getUrl() { echo $this->url.'/'.$this->ti tle; } }
面向對象中 public、protected、private 三種訪問控制模式的區別是:
public(公有):公有的類成員可以在任何地方被訪問。
protected(受保護):受保護的類成員則可以被其自身以及其子類和父類訪問。
private(私有):私有的類成員則只能被其定義所在的類訪問。
接口 和 抽象類 分別是什么?有哪些區別?
抽象類
抽象類通過 abstract 關鍵字來聲明的。
抽象類不能被實例化,只能使用 extends 繼承抽象類。
抽象類中至少包含一個抽象方法。
抽象類中的抽象方法只是聲明了其調用方式或參數,所有的抽象方法都是空的。
抽象類中的抽象方法天生就是要被子類重寫的。
抽象類繼承的時候,子類必須實現父類中的所有抽象方法。
子類中的方法的訪問控制必須和父類中的一樣或者更為寬松;
子類中定義了一個可選參數,而父類抽象方法的聲明里沒有,則也是可以正常運行的。
接口
接口通過 interface 關鍵字來聲明的。
接口不能被實例化,只能使用 implements 實現接口。
接口中的成員常量和方法都是 public 的,這是接口的特性。
接口中的方法也只是聲明了其調用方式或參數,所有的方法都是空的。
接口中的方法天生就是要被子類實現的。
接口實現的時候,類中必須實現接口中定義的所有方法,否則會報一個致命錯誤。
類可以實現多個接口,用逗號來分隔多個接口的名稱。
區別
抽象類和接口實現的功能十分相似,最大的不同是接口能實現多繼承。
Static 關鍵字
聲明類屬性和方法為靜態的,可以不用實例化類而直接訪問。
靜態屬性不能通過一個類已實例化的對象類訪問,但是靜態方法可以訪問。
靜態方法不需要通過對象即可調用。所以 $this 在靜態方法中不可以使用。
Final 關鍵字
PHP5中新增的。
如果父類中的方法被聲明為final,則子類無法覆蓋該方法。
如果一個類被聲明為 final,則不能被繼承。
多繼承
trait test_a { function fun_a() { echo "a"; } } trait test_b { function fun_b() { echo "b"; } } class test { use test_a test_b; function fun_a() { echo 'ca'; } } $t = new test; $t->fun_a(); $t->fun_b();
序列化/反序列化
序列化:把本來不能直接存儲的數據轉換成可存儲的數據,并且不會丟掉數據格式
serialize();
反序列化:把序列化后的數據,轉換成我們需要的格式
unserialize();
案例
// 數組 $arr = array( 'name'=>'mike' 'birth'=>'0101' 'sex'=>1 ); //序列化 $serialized_data = serialize($arr); echo $serialized_data; // 得到 // a:3:{s:4:"name";s:4:"mike";s:5:"birth";s:4:"0101";s:3:"sex";i:1;} //反序列化 $res = unserialize($serialized_data); var_dump($res); //得到 /* array(3) { ["name"]=> string(4) "mike" ["birth"]=> string(4) "0101" ["sex"]=> int(1) } */