===================================================
PHP的物件導向:
對象是客觀存在的一個實體。
類是對對象抽象的一個描述。
概念:對象(實體)、類、 類與對象的關係。
oop物件導向編程的特點:封裝、繼承、多態
類和對象的關係:
類的執行個體化結果就是一個對象(使用new關鍵字)
對對象的抽象描述就是一個類
===================================================
一、如何定義一個類,和使用
1.1 文法格式:
[修飾符] class 類名 [extends 父類] [implements 介面1[,介面2...]]{
【成員屬性】定義變數
【成員方法】定義函數
}
1.2 成員屬性格式:
修飾符 $變數名[=預設值]; 如:public $name="zhangsan";
注意:成員屬性不可以是帶運算子的運算式、變數、方法或函數的調用。 如:
public $var3 = 1+2;
public $var4 = self::myStaticMethod();
public $var5 = $myVar;
正確定義方式:
public $var6 = 100; //普通數值(4個標量:整數、浮點數、布爾、字串)
public $var6 = myConstant; //常量
public $var7 = self::classConstant; //靜態屬性
public $var8 = array(true, false); //數組
常用的屬性修飾符:public、protected、private、static、var
1.3 成員方法格式:
[修飾符] function 方法名(參數..){
[方法體]
[return 傳回值]
}
常用的方法修飾符:public、protected、private、static、abstract、final
1.4 對象:類的執行個體化就會產生一個對象。
如: $p = new Person();
1.5 $this 關鍵字: 表示自己,表示當前使用對象,*哪個對象調用代表哪個
1.我們在類中調用自己的成員屬性或方法都是使用 $this->調用。
2.注意:靜態方法不可以使用$this關鍵字
===================================================
二、構造方法和析構方法
2.1. 構造方法:
1.當我們通過new關鍵字來建立一個對象時,第一個自動執行的方法稱為構造方法。
2.方法名__construct(); 主要用於初始化對象。
(在php4.0時可使用與類名重名的方法作為構造方法)
2.2. 析構方法:當這個對象被銷毀時最後自動調用的方法,稱為析構方法。
1.__destruct(); 目的是釋放資源(如關閉串連、檔案,釋放資源)
2.對象被銷毀時最後自動調用
===================================================
三、封裝(存取控制)
3.1 封裝:就是將"屬性" private或protected 私人,並提供公有的setter放置與getter取值方法
public(公有) protected(受保護) private(私人)
===========================================================
在本類中 Y Y Y
在家族中 Y Y N
在類外邊 Y N N
public 類外需要調用此類內的方法或屬性時使用
protected 類外不需要調用,而家族內需要使用
private 用於安全資訊,只用於當前類
===================================================
四、 重載
4.1 屬性重載中的四個魔術方法:__set() __get() __isset() __unset()
__get():當我們直接輸出一個對象中的非公有屬性時會自動調用的方法,
並將屬性名稱以第一個參數傳進去。
__get($name){...} //外部:$m->priAge;
__set():當我們直接設定一個對象中的非公有屬性時會自動調用的方法,
並將屬性名稱以第一個參數,值作為第二參數傳進去。
__set($name,$value){...} //外部:$m->priAge = 100;
__isset():驗證一個對象屬性isset($this->name) 或 empty($this->name)時, $this->name是一個非公有屬性時,自動調用此方法。
public function __isset($param){
return isset($this->$param);
}
__unset()當銷毀一個對象屬性unset($this->name), $this->name是一個非公有屬性時,自動調用此方法。
public function __unset($param){
unset($this->$param);
}
4.2 方法的重載:
mixed __call ( string $name , array $arguments )
mixed __callStatic ( string $name , array $arguments ) php5.3.0支援
1.當調用一個不可存取方法(如未定義,或者不可見)時,__call() 會被調用。
2.當在靜態方法中調用一個不可存取方法(如未定義,或者不可見)時,__callStatic() 會被調用。
第一個參數表示方法名,第二參數表示調用時的參數列表(數群組類型)
class A {
//調用不存在的方法
public function __call($methodName,$args) {
echo $methodName;
print_r($args);
}
//調用不存在的靜態方法
static public function __callStatic($methodName,$args) {
echo '
'.$methodName;
print_r($args);
}
}
$a = new A;
$a->say('a','b');
A::test('c','d');
===================================================
五、 繼承
5.1 繼承:extends
*繼承的目的:為了減少重複的代碼。
假如B類繼承A類,那麼就繼承了A中所有非私人屬性和方法.其中A叫父類(基類)B叫子類(衍生類別)。
class B extends A{
....
}
1.*parent:若子類出現覆蓋父類的方法,那麼想調用被覆蓋掉的父類方法,並可以跟子類的方法融合為一起
格式:parent::父類方法 | 父類名稱::父類方法
class A{
public function __construct(){
//....
}
}
class B extends A{
public function __construct(){
parent::__construct();//注意要調用一下父類的構造方法
//....
}
}
2.繼承的特性
1、PHP支援單繼承,一類只能繼承一個父類
2、PHP支援多層繼承,可以有子孫類
3、子類會繼承父類所有屬性和方法,但是私人的屬性和方法不能調用
3.屬性的繼承
1、私人的屬性不會被覆蓋,其他會被覆蓋。
2、屬性的修飾只能更加鬆散,不能更加嚴謹。 鬆散性:public > protected > private
3、如果子類中有與父類同名的屬性,父類有public $name 子類只能使用public修飾
3、如果子類中有與父類同名的屬性,父類有protected $name 子類能使用protected,public修飾
4.方法的繼承
1、所有方法可以被繼承,但是私人的方法不能被使用
2、如果子類有與父類同名的方法,那麼除了私人的方法,其他都被覆蓋掉。
3、如果子類有與父類同名的方法,方法的修飾只能更加鬆散,不能更嚴謹。
===================================================
六、 final、static和const
*記憶體邏輯上:常量區(常量、靜態屬性)、代碼區(類、函數)、棧記憶體(普通的小的變數)、堆記憶體(大的變數)
6.1 final關鍵字:主要用於修飾類與成員方法
目的:一是為了安全,二是沒有必要
1.使用final關鍵字修飾類,表示這個類不能被繼承,防止有子類的覆蓋
2.使用final關鍵字修飾的方法,不可以在子類中被覆蓋(重寫)。
3.使用final關鍵字不能修飾屬性
final class B {
final public function A {
..
}
}
---------------------------------------------------------------
6.2 static關鍵字:表示靜態意思,用於修飾類的屬性和方法
static關鍵字修飾 屬性/方法 稱為 靜態屬性/靜態方法,
注意:靜態方法在執行個體化後的對象不可以訪問 //$對象名->靜態方法名
1.可以不用new(執行個體化)就可以直接使用方法或屬性
*外部調用:類名::方法名 | 類名::屬性名稱
*類中調用:self::靜態屬性名 | self::靜態方法名
*2.靜態屬性是共用的。也就是調用多個對象也是指向同一個地址
3.在靜態方法中不可以使用非靜態內容。就是不讓使用$this
4.在一個類的方法中若沒有出現$this的調用,預設此方法為靜態方法。
5.static不能修飾類
---------------------------------------------------------------
6.21 設計模式。目的:節省資源
1、單例設計模式 2、工廠設計模式 3、 抽象工廠設計模式
class Single
{
//定義一個靜態屬性,用來存放對象
static private $obj = null;
//私人化構造方法。不能在類的外部執行個體化對象
private function __construct() {}
//執行個體化對象
static public function test() {
//如果沒有對象,我們就允許它new一個對象
if(!self::$obj) {
self::$obj = new Single();//建立對象
}
//有了對象,就直接返回之前的對象
return self::$obj;
}
//單例不允許複製
public function __clone() {
trigger_error('錯誤', E_USER_ERROR);
}
}
$s1 = Single::test(); var_dump($s1);
$s2 = Single::test(); var_dump($s2); //調用同一個對象
$s3 = clone $s2; //報錯
---------------------------------------------------------------
6.3. const關鍵字: 在類中修飾成員屬性,將其定義成常量(不可修改的),
1.一般要求常量名都是大寫的,沒有“$”符 沒有其他修飾符(public)
2.定義格式:const 成員常量名="值";
3.使用:
*外部調用:類名::成員常量名;
*類中調用:self::成員常量名;
---------------------------------------------------------------
6.4. 檢測當前對象是屬於誰的類(家族類也是)
1.instanceof 用於確定一個 PHP 變數是否屬於某一類 class 的執行個體:
class A {}
class B extends A {}
$b = new B;
if($b instanceof A) {echo 'y';}
2.is_a — 如果對象屬於該類或該類是此對象的父類則返回 TRUE
===================================================
七、 類型約束
1. 類型約束可以使用的類型是:數組,對象,回呼函數。
若指定的一個類名,那麼可傳入本類及子類的對象進去。
可以使用的約束類型:(複合類型)數組array,類名、抽象類別名、介面名
class MyClass
{
//第一個參數必須為類OtherClass的一個對象
public function test(OtherClass $otherclass) {
**可以傳入別的類,調用別的類的方法和屬性
echo $otherclass->var;
//同這裡
if( $otherclass instanceof Hanzi){
$otherclass->qinqin();
}
}
//第一個參數必須為數組
public function test_array(array $input_array) {
print_r($input_array);
}
}
===================================================
八、其他魔術方法:
1. 對象複製clone 複製一個對象,因為對象屬於參考型別,普通的“=”號屬於引用賦值,
所有需要clone來複製一份。
魔術方法:__clone() 當執行clone複製時會自動調用的方法。
class A {
public function __clone() {
//自動執行
}
}
$a = new A;
$b = clone $a; //複製,是兩個對象
-----------------------------------------------------------------
2. __toString()方法:魔術方法,當我們直接要輸出一個對象時,如echo $a,print $a,
那麼會自動調用的方法。
注意:__toString()方法必須返回一個字串類型的值。
class A {
public function __toString() {
return '這是一個對象,不允許ehco,print...';
}
}
$a = new A;
echo $a; //報錯
-----------------------------------------------------------------
3. *自動載入"類函數"__autoload(類名):
當new 執行個體化一個對象時,這個類若不存在,則自動調用此函數,並將類名存入參數
我可以使用這個實作類別的自動載入。
function __autoload($className) {
include './autoload/'.$className.'.class.php';
}
$a = new A;
$a->say(); //say
//在 autoload/A.class.php下
class A{
public function say() {
echo 'say';
}
}
-----------------------------------------------------------------
4. __invoke把對象當成函數使用的時候自動調用
class A {
public function __invoke() {
echo 'aa';
}
}
$a = new A;
$a(); //aa
===================================================
九、 對象序列化(序列化)(webservice XML)(在對象持久化儲存、和傳輸中使用)
serialize() -- 序列化
unserialize() -- 還原序列化
1.php裡面的值都可以使用函數serialize()來返回一個包含位元組流的字串來表示。
2.unserialize()函數能夠重新把字串變回php原來的值。
3.序列化一個對象將會儲存對象的所有變數,但是不會儲存對象的方法,只會儲存類的名字。
1.__sleep(): 是執行序列化時自動調用的方法,目的是實現資源類型的屬性的關閉操作。
@@sleep方法需要返回一個數組,其中數組中的值是序列化時要保留的屬性名稱
2.__wakeup():是在執行反序列化時自動調用的方法,目的是實現資源屬性的開啟(sleep方法關閉的資源)
//執行個體:
class A {
public $name1 = 'xiaohei';
public $name2 = 'xiaobai';
public function demo() {
return 'aa';
}
//序列化自動調用的方法
public function __sleep() {
return array('name2'); //只想儲存name2,就返回name2
}
//還原序列化自動調用的方法
public function __wakeup() {
echo '###';
}
}
$a = new A;
//序列化
$data = serialize($a);
//存入檔案
file_put_contents('./1.txt', $data);
//獲得資料
$str = file_get_contents('./1.txt');
echo $str; //O:1:"A":1:{s:4:"name";s:7:"xiaohei";}
//還原序列化
$tmp = unserialize($str);
print_r($tmp); //A Object ( [name] => xiaohei )
-------------------------------------------------------------------------------------
JSON格式的字串進行編碼/解碼
json_encode:對變數進行 JSON 編碼
json_decode:對 JSON 格式的字串進行編碼
$arr = array('id'=>1, 'name'=>'jack');
$str1 = json_encode($arr);
echo $str1; //{"id":1,"name":"jack"}
$a = json_decode($str1, true); //加true返回array,否則返回object
echo $a; //Array ( [id] => 1 [name] => jack )
===================================================
十、 抽象類別:
目的:抽象類別對於子類(實作類別),有一個約束的作用,
特點:
//1.定義抽象類別
abstract class A {
//2.定義抽象方法
abstract public function test1();
abstract public function test2();
//3.可以有普通方法和屬性,不需要子級實現
public function demo() {}
public $name = 'aa';
//4.不能定義抽象屬性 Fatal error
abstract public $age = 18;
}
class B extends A {
//5.@@繼承了抽象類別的"普通類"必須實現抽象類別的"所有抽象方法"
public function test1() {}
public function test2() {}
//6.包含了抽象方法的類必須是抽象類別,Fatal error
abstract function test3() {}
}
abstract class C extends A {
//7.不能覆蓋抽象方法,Fatal error
abstract public function test1() {}
//8.可以繼承抽象類別的同時添加抽象方法
abstract public function test3();
}
//8.不能執行個體化,Fatal error
$c = new C;
===================================================
十一、 介面:
目的:同抽象類別相同,是更具體的抽象類別
假如一個抽象類別中所有的方法都是抽象的,那麼我們可以使用另外一種方式定義:介面
介面使用關鍵字interface來定義,介面中只能有常量與抽象方法。
//1.定義介面
interface A {
//2.介面不能有普通屬性,Fatal error
public $name = 'aa';
//3.介面不能有普通方法,Fatal error
public function test() {}
//3.但可以定義常量
const HOST = 'aa';
//4.定義介面方法,不需要abstract
public function test1();
}
interface B {
//5.介面之間是繼承關係,重複定義Fatal error
const HOST = 'bb';
public function test2();
}
class C {}
//6.可以同時繼承"單"類、實現"多"介面(先繼承,後實現)
class D extends C implements A,B {
//7.@@繼承了抽象類別的"普通類"必須實現抽象類別的"所有抽象方法"
public function test1() {}
public function test2() {}
}
抽象類別和介面總結:
1.目的:制定規範,為了限制其子類
2.選擇:如果規範中需要有"普通方法"就選擇抽象類別
3.區別:
1.定義關鍵字不同。抽象類別:abstract 介面:interface
2.繼承/實現關鍵字不同。抽象類別:extends 介面:implements
3.抽象類別可以有普通方法,介面不能有普通方法
4.抽象類別只能被單繼承,介面可以多實現
5.介面不能有成員屬性,只有常量與抽象方法
===================================================
十二、多態
定義:對於“同一個方法”,傳入“不同對象”,實現了不同的效果
class Meizi {
public function meet($obj) {
//限制了對象必須有qinqin()這個方法
if( $obj instanceof Hanzi){
//同一個方法
$obj->qinqin();
}else{
echo '你不會親親這個功能!';
}
}
}
//抽象類別
abstract class Hanzi
{
abstract public function qinqin();
}
//大屌絲類
class DDS extends Hanzi {
public function qinqin() {
echo '被妹子打了一巴掌,這就是DDS的命運';
}
}
//高富帥類
class GFS extends Hanzi {
public function qinqin() {
echo '不僅僅親親,還啪啪啪,這是高富帥的命運';
}
}
//萌妹子類
class MengMeizi {}
$m = new Meizi;
$dds = new DDS;
$gfs = new GFS;
$mmz = new MengMeizi;
//傳入對象
echo $m->meet($dds); //實現了DDS的效果
echo $m->meet($gfs); //實現了GFS的效果
//沒有限制
echo $m->meet($mmz); //你不會親親!
@@多態的兩個執行個體:
./1.通過介面實現多態的應用.php
./2.通過普通類實現多態的應用.php
===================================================
十三、異常處理:
在php5中有一種新的錯誤處理機制--異常處理:(採用物件導向方式的)
涉及的類:Exception異常類
Exception類結構:
class Exception
{
protected $message = 'Unknown exception'; // 異常資訊
protected $code = 0; // 使用者自訂異常代碼
protected $file; // 發生異常的檔案名稱
protected $line; // 發生異常的程式碼號
function __construct($message = null, $code = 0);
final function getMessage(); // 返回異常資訊
final function getCode(); // 返回異常代碼
final function getFile(); // 返回傳生異常的檔案名稱
final function getLine(); // 返回傳生異常的程式碼號
final function getTrace(); // backtrace() 數組
final function getTraceAsString(); // 已格成化成字串的 getTrace() 資訊
/* 可重載的方法 */
function __toString(); // 可輸出的字串
}
使用:
try{
throw new Exception("年齡不可以為負數"); //異常拋出
}catch(Exception $e){
//異常處理
echo $e->getmessage();
}
執行個體:
function addUser($username) {
if($username="xiaobai") {
//添加成功
}else {
//添加失敗
throw new Exception('添加失敗');
}
}
function updateUser($username) {
if($username = "xiaohei") {
//修改成功
}else {
//修改失敗
throw new Exception('修改失敗');
}
}
try {
addUser('xiaobaia');
updateUser('xiaohei');
}catch(Exception $e) {
echo '失敗資訊是:'.$e->getMessage();
}
@@當捕獲到一個異常後,try()塊裡面的後續代碼不繼續執行