成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

PHP_OOP

RiverLi / 1444人閱讀

摘要:特殊在,方法被對(duì)象調(diào)用執(zhí)行時(shí),會(huì)自動(dòng)確定是那個(gè)對(duì)象調(diào)用的該方法,會(huì)使用該對(duì)象為方法內(nèi)的賦值構(gòu)造析構(gòu)類(lèi),沒(méi)有作用域,作用域,只是講,函數(shù)內(nèi)和函數(shù)外。析構(gòu)在對(duì)象消失對(duì)象被銷(xiāo)毀時(shí),也會(huì)自動(dòng)執(zhí)行一個(gè)方法,稱(chēng)之為析構(gòu)方法。

相關(guān)定義

對(duì)象(object):現(xiàn)實(shí)生活中的實(shí)體,在編程語(yǔ)言中的體現(xiàn)。實(shí)體都有屬性和功能。一組數(shù)據(jù),和操作管理這些數(shù)據(jù)的操作,定義在一起就形成了一個(gè)實(shí)體,稱(chēng)之為對(duì)象。(屬性和方法的集合)


屬性(property),對(duì)象中,對(duì)象所擁有的數(shù)據(jù),稱(chēng)之為對(duì)象的屬性。


方法(method):對(duì)象中,對(duì)象所擁有的管理數(shù)據(jù)的能力,稱(chēng)之為方法。

在php中,對(duì)象通過(guò)對(duì)類(lèi)的實(shí)體化形成的對(duì)象。

類(lèi)(class): 對(duì)象的模子。 一類(lèi)的對(duì)象抽取出來(lái)。一個(gè)將對(duì)象的行為和屬性的一個(gè)抽象。就是一個(gè)定義。規(guī)定了對(duì)象應(yīng)該有哪些屬性,應(yīng)該有哪些操作(方法)。


實(shí)例化:一個(gè)動(dòng)作,根據(jù)類(lèi)中所定義的對(duì)象的特征,形成一個(gè)對(duì)象的過(guò)程。

注意: php 中,對(duì)象一定是通過(guò)類(lèi)的實(shí)例化來(lái)的。類(lèi)的地位,只是得到對(duì)象的方法。

可以使用php 預(yù)定義的類(lèi)。
stdclass . 通過(guò)實(shí)例化該類(lèi),就可以得到一個(gè)對(duì)象。
實(shí)例化: 通過(guò)關(guān)鍵字new 完成.

基本語(yǔ)法 定義類(lèi)

class 關(guān)鍵字

class 類(lèi)名 {
    成員
}

在定義一個(gè)類(lèi)的時(shí),需要知道這個(gè)類(lèi)所實(shí)例化的對(duì)象,應(yīng)該具有哪些屬性和方法。

增加屬性: 對(duì)象所擁有的數(shù)據(jù),就是定義在類(lèi)中變量。
增加方法: 對(duì)象所擁有的操作,可執(zhí)行代碼就是操作.定義在類(lèi)中的函數(shù).

注意:類(lèi)中的成員(屬性和方法),需要增加訪問(wèn)修飾限定符,簡(jiǎn)單的增加--public
在聲明成員時(shí),不能直接使用變量,需要使用關(guān)鍵字來(lái)聲明

實(shí)例化對(duì)象

通過(guò)類(lèi)得到對(duì)象 ,操作符 new 完成.

實(shí)例化好后,典型的應(yīng)該保存在變量?jī)?nèi)

$stu = new Student();

一個(gè)類(lèi),可以實(shí)例化多個(gè)對(duì)象,多個(gè)不同的對(duì)象

對(duì)象操作屬性和方法

使用操作符 ->

// 對(duì)象 -> 成員
$stu->a; // 10    

注意,屬性名前$沒(méi)有了

如果存在$, 語(yǔ)法就 變成 屬性名(屬性標(biāo)識(shí)符) 由變量充當(dāng),變成了可變屬性的語(yǔ)法

$property_name = "stu_id";
echo $stu->$property_name;

屬性名,同變量名一樣,嚴(yán)格區(qū)分大小寫(xiě)。

保存數(shù)據(jù)標(biāo)識(shí)符,就區(qū)分大小寫(xiě)。
如果是結(jié)構(gòu)標(biāo)識(shí)符,就區(qū)分大小寫(xiě)。 比如:函數(shù),類(lèi),方法名。

訪問(wèn)方法:

$stu->study();

方法名,不區(qū)分大小寫(xiě)
方法名,支持可變方法,方法名有變量來(lái)代替

類(lèi)名,可以使用變量來(lái)代替。

$class_name = "Student"; 
$stu = new $class_name;
屬性

可以在定義時(shí),為屬性直接設(shè)置初始值,但是必須已經(jīng)存在的數(shù)據(jù)(類(lèi)似于函數(shù)參數(shù)的默認(rèn)值)
如果沒(méi)有默認(rèn)值,則值為null

屬性,每個(gè)對(duì)象的同名屬性,都可以具有不同的值, 每個(gè)對(duì)象所擁有的屬性時(shí)不同的數(shù)據(jù)空間。
因?yàn)樵趯?shí)例化對(duì)象時(shí),php會(huì)為每個(gè)對(duì)象分配一個(gè)獨(dú)立的空間,保存對(duì)象的屬性

由于,常規(guī)的,每個(gè)對(duì)象,應(yīng)該擁有不同的屬性值。
建議,在得到該對(duì)象時(shí),應(yīng)該對(duì)對(duì)象所擁有的屬性,進(jìn)行初始化。

方法

方法,也是屬于某個(gè)對(duì)象。但是通常,方法內(nèi)所操作的數(shù)據(jù),都是該對(duì)象所擁有的數(shù)據(jù)。

在使用對(duì)象調(diào)用某個(gè)方法時(shí),會(huì)自動(dòng)地將當(dāng)前對(duì)象傳遞到該方法內(nèi)(類(lèi)似于參數(shù)的傳遞)。 方法內(nèi),會(huì)自動(dòng)使用變量 $this 來(lái)接收這個(gè)對(duì)象。因此,可以在方法內(nèi),通過(guò)$this方法調(diào)用該方法的對(duì)象。

如何在方法中,訪問(wèn)對(duì)象,$this
$this,這個(gè)對(duì)象。調(diào)用該方法的對(duì)象。

$this 就是一個(gè)方法內(nèi)的局部變量。特殊在,方法被對(duì)象調(diào)用執(zhí)行時(shí),PHP會(huì)自動(dòng)確定是那個(gè)對(duì)象調(diào)用的該方法,會(huì)使用該對(duì)象為方法內(nèi)的$this賦值

構(gòu)造&析構(gòu)

類(lèi),沒(méi)有作用域, 作用域,只是講,函數(shù)內(nèi)和函數(shù)外。

注意,想訪問(wèn)到對(duì)象的成員(屬性和方法),一定要先找到對(duì)象和方法。

class Student {
    public $stu_id;
    public $stu_name;
    
    public function sayName() {
        echo $this->stu_name; // zf
        var_dump($stu_name); // 報(bào)錯(cuò)   Undefined variable
        var_dump($GLOBALS["stu_name"]); // 報(bào)錯(cuò) Undefined variable 
    }
    
}

$stu = new Student();

$stu->stu_id = "16.7.3";
$stu->stu_name = "zf";

$stu->sayName();
    

類(lèi)中定義的屬性,不是相當(dāng)于類(lèi)中定義的方法的全局變量。不能直接在方法中使用屬性變量的形式訪問(wèn):

如果直接操作(輸出)這個(gè)類(lèi)名,則不會(huì)當(dāng)做類(lèi)來(lái)看待,而是當(dāng)做常量來(lái)看待。

構(gòu)造

在得到對(duì)象時(shí),幾乎都需要,對(duì)對(duì)象屬性進(jìn)行初始化,而且都是一樣的操作。在一個(gè)操作中完成初始化,然后對(duì)該方法進(jìn)行多次調(diào)用。

在實(shí)例化類(lèi)得到對(duì)象時(shí)被自動(dòng)地調(diào)用
主要承擔(dān)的工作是初始化對(duì)象屬性

對(duì)象的屬性初始化
只要得到了對(duì)象,對(duì)象的屬性就應(yīng)該被賦予新的值。
如果某些屬性,在對(duì)象出現(xiàn)時(shí),可以被設(shè)置為某些特定的值。就可以在聲明類(lèi)時(shí),為聲明的屬性設(shè)置默認(rèn)值。

stu_id = $id;
        $this->stu_name = $name;
    }  
    

調(diào)用該方法初始化

stu_id = $id;
            $this->stu_name = $name;
            
        }
        
    }


    $stu1 = new Student;
//    $stu1->stu_id = 100;
//    $stu1->stu_name = "李尋歡";

    $stu1->init(100,"李尋歡");
        
    var_dump($stu1);

再前進(jìn)一步:
是否可以在實(shí)例化后,自動(dòng)調(diào)用該初始化方法的方法。
PHP的 oop 機(jī)制,在new完成時(shí),會(huì)試著調(diào)用一個(gè)叫做 __constructor() 的方法.如果將初始化的代碼,寫(xiě)到這個(gè)方法內(nèi),就可以完成自動(dòng)初始化。

該方法,在通過(guò)類(lèi)實(shí)例化對(duì)象,也叫構(gòu)造對(duì)象時(shí),被自動(dòng)調(diào)用的,常常用于初始化對(duì)象,這個(gè)方法被叫做 構(gòu)造方法。(此方法,就是比普通方法多了一個(gè)自動(dòng)調(diào)用的功能)
只要得到了對(duì)象,對(duì)象的屬性就應(yīng)該被賦予新的值


由于不用去調(diào)用這個(gè)構(gòu)造函數(shù),如何傳參呢?
在實(shí)例化時(shí),通過(guò)在類(lèi)名后,增加實(shí)例化列表形式,為構(gòu)造函數(shù)方法傳參。

stu_id = $id;
            $this->stu_name = $name;
            
        }    
        
    }


    $stu1 = new Student(100,"李尋歡");

此時(shí),需要注意,實(shí)例化時(shí),類(lèi)名后,可以增加括號(hào),取決于,該對(duì)象的構(gòu)造方法,是否需要參數(shù),如果不需要,則可以省略,或者是一個(gè)空括號(hào)。如果需要?jiǎng)t一定有括號(hào),括號(hào)內(nèi)是實(shí)參列表

$stu1 = new Student;
$stu2 = new Student();

// 需要參數(shù)
$stu2 = new Student("1000","阿飛");

構(gòu)造方法的兼容性問(wèn)題
PHP5,構(gòu)造方法的名字, 就是 __construct(); 在php5之前,構(gòu)造方法名字與類(lèi)同名。為了兼容,也同時(shí)支持這個(gè)與類(lèi)同名的構(gòu)造方法

class Student {
    
    public function Student ( $id, $name ) {

    }

}

如果同時(shí)出現(xiàn),如何處理
先寫(xiě)__construct(); 后寫(xiě)Student;

找,__construct.

先寫(xiě)Stuendt(); 后寫(xiě)__construct();

找 __construct. 有一個(gè)錯(cuò)誤提示。

常見(jiàn)的寫(xiě)法:

public function __construct ( $id, $name ) {
    $this->Student($id,$name);
}
public function Student ( $id,$name ) {
    $this->stu_id = $id;
    $this->stu_name = $name;
}

構(gòu)造是這個(gè)對(duì)象來(lái)的時(shí)候的方法,對(duì)象實(shí)例化類(lèi)的時(shí)候,才形成的。

如果某些屬性,在對(duì)象出現(xiàn)時(shí),可以被設(shè)置為某些特定的值。就可以在聲明類(lèi)時(shí),為聲明的屬性設(shè)置默認(rèn)值

如果沒(méi)有定義__construct()可以不用執(zhí)行
但是一旦定義了構(gòu)造方法,那么構(gòu)造(實(shí)例化)的過(guò)程,一定要包括這個(gè)調(diào)用構(gòu)造方法的過(guò)程(構(gòu)造方法一定會(huì)執(zhí)行)。

析構(gòu)

在對(duì)象消失(對(duì)象被銷(xiāo)毀時(shí)),也會(huì)自動(dòng)執(zhí)行一個(gè)方法,稱(chēng)之為析構(gòu)方法。
析構(gòu)方法名字為 __destruct();
也會(huì)自動(dòng)被調(diào)用。完全取決于這個(gè)對(duì)象是否被銷(xiāo)毀。

該方法,用于釋放對(duì)象所占用的額外資源。并不是釋放對(duì)象本身.(對(duì)象本身,是由垃圾回收機(jī)制去銷(xiāo)毀) 不是對(duì)象本身的內(nèi)存空間。

public function __destruct () {
    // 釋放資源
    mysql_close();
}

什么情況下,對(duì)象會(huì)被銷(xiāo)毀:

腳本周期結(jié)束,自動(dòng)銷(xiāo)毀,幾個(gè)對(duì)象銷(xiāo)毀幾次。

銷(xiāo)毀保存該對(duì)象的變量時(shí):

unset($stu1);

保存對(duì)象的變量,被賦值了其他數(shù)據(jù)。 任何新值都可以,甚至是原來(lái)類(lèi)的新對(duì)象。都會(huì)導(dǎo)致原對(duì)象被銷(xiāo)毀。常見(jiàn)的使用是null.表示銷(xiāo)毀對(duì)象的含意

$stu = null;

對(duì)象間的copy&clone

對(duì)象間的復(fù)制
支持引用傳遞,不用 & 符號(hào), 因此不能通過(guò) = 賦值的形式,得到一個(gè)新的對(duì)象。

克隆 clone
利用已有的對(duì)象,得到相同的新對(duì)象。
需要使用關(guān)鍵字 clone 完成。
新對(duì)象 = clone 舊對(duì)象.

常見(jiàn)的操作,在克隆對(duì)象時(shí),需要對(duì)對(duì)象的某些特殊屬性進(jìn)行修改。意味著,在克隆的時(shí),需要做一些特殊的處理。

使用 在克隆時(shí),自動(dòng)調(diào)用的方法, __clone() 來(lái)實(shí)現(xiàn)。

自動(dòng)使用克隆出來(lái)的對(duì)象,來(lái)調(diào)用這個(gè)__clone()方法,意味著,該方法內(nèi)的$this,表示新對(duì)象;

public function __clone () {
    // $this 指向克隆對(duì)象
    $this->stu_id = "1000";
}

$stu3 = clone $stu1;

PHP中得到新對(duì)象兩個(gè)方法

實(shí)例化(通過(guò)類(lèi)構(gòu)造對(duì)象) ,需要使用構(gòu)造方法對(duì)對(duì)象進(jìn)行初始化。

克隆(通過(guò)對(duì)象克隆新對(duì)象) ,得到一個(gè)屬性值與克隆的就對(duì)象一模一樣的對(duì)象,但是,可以通過(guò)__clone 方法進(jìn)行修改。

魔術(shù)方法
特定的情況下,會(huì)被自動(dòng)調(diào)用
__ 魔術(shù)方法

靜態(tài)成員

場(chǎng)景: 學(xué)生類(lèi),每個(gè)學(xué)生是一個(gè)類(lèi)的對(duì)象,需要統(tǒng)計(jì),當(dāng)前已經(jīng)存在幾個(gè)學(xué)生?

如何定義這個(gè)計(jì)數(shù)器?

不能直接用屬于對(duì)象的屬性,每個(gè)對(duì)象所獨(dú)有的。
應(yīng)該找一個(gè)對(duì)象所共有的數(shù)據(jù)。
構(gòu)造方法靜態(tài)局部變量,也是不行,原因析構(gòu)時(shí)不能使用。

public function __construct () {
    $this->count++;
    static $count = 0;
    $count ++;
    echo $coun;
}

public function __destruct () {
    $this->count--;
    $count--;
}

應(yīng)該找一個(gè)能夠被對(duì)象所共有的數(shù)據(jù)并且能夠在多個(gè)方法內(nèi)使用的變量。
使用全局變量即可,在方法內(nèi),是可以通過(guò)$GLOBALS訪問(wèn)到全局變量。

public function __construct () {
    $GLOBALS["count"]++;
}

public function __destruct () {
    $GLOABLS["count"]--;
}

全局變量不應(yīng)該屬于任何的對(duì)象或者類(lèi).$count 與 類(lèi) 沒(méi)有絲毫的邏輯上的聯(lián)系.

應(yīng)該找一個(gè)能夠被對(duì)象所共有并且能夠在多個(gè)方法內(nèi)使用的變量,還應(yīng)該與當(dāng)前的對(duì)象類(lèi)有邏輯的關(guān)系的數(shù)據(jù)?
可以使用類(lèi)的靜態(tài)成員.

靜態(tài)成員,指的是邏輯上被所有對(duì)象所共享,屬于類(lèi)的成員稱(chēng)之為類(lèi)的靜態(tài)成員。

靜態(tài)屬性和靜態(tài)方法
保存數(shù)據(jù)的是靜態(tài)屬性,執(zhí)行功能的是靜態(tài)方法

靜態(tài)屬性

使用static 關(guān)鍵字聲明的屬性。
該靜態(tài)屬性,在邏輯上,是定義在類(lèi)上面的屬性。(與定義對(duì)象上的屬性對(duì)應(yīng)).

public static $stu_count = 0;

保證一個(gè)類(lèi),對(duì)應(yīng)一個(gè)屬性,意味著,該類(lèi)的所有對(duì)象共用這個(gè)屬性。

訪問(wèn)靜態(tài)屬性

通過(guò)類(lèi)來(lái)訪問(wèn),再利用靜態(tài)訪問(wèn)符號(hào)(雙冒號(hào)::,范圍解析操作符)

類(lèi)::成員

Student::$stu_count++;

:: 的訪問(wèn)稱(chēng)之為靜態(tài)訪問(wèn),相對(duì)的箭頭(->)稱(chēng)為非靜態(tài)訪問(wèn)(對(duì)象訪問(wèn))

var_dump(Student::$stu_count);

在訪問(wèn)時(shí),如果是在類(lèi)內(nèi)訪問(wèn):則可以使用self關(guān)鍵字,來(lái)代替當(dāng)前類(lèi).

self::$stu_count++;

注意,$this和self的區(qū)別
$this表示的是這個(gè)對(duì)象。 $this->
self表示類(lèi)自己。 self::
parsent當(dāng)前父類(lèi) parent::

PHP還支持的寫(xiě)法:
對(duì)象也支持靜態(tài)訪問(wèn),但是需要使用靜態(tài)訪問(wèn)符號(hào)。容易造成混淆,不建議經(jīng)常使用。

$stu3::$stu_count;
靜態(tài)方法

靜態(tài)方法的邏輯意義,也是定義在類(lèi)上的方法。同樣,調(diào)用形式,也是通過(guò)類(lèi):: 來(lái)訪問(wèn)

定義:

public static function sayCount () {
    echo "run";
}

訪問(wèn):

Student::sayCount();

靜態(tài)方法和非靜態(tài)方法的主要區(qū)別,在于是否可以接收一個(gè)對(duì)象的執(zhí)行環(huán)境
就是是否可以為方法內(nèi)的$this 是否可以被賦值

只有在對(duì)象調(diào)用方法時(shí),才能將對(duì)象的執(zhí)行環(huán)境傳遞到方法內(nèi),$this才可以被賦值.

Class Student {
    public static $stu_count = 0;
    
    public static function  sayCount () {
        
        var_dump($this); //報(bào)錯(cuò)
        
        echo "run";
        
    }
    
}

$stu1 = new Student();


Student::sayCount();

無(wú)論靜態(tài)和非靜態(tài)方法,都是一個(gè)函數(shù),找到他并執(zhí)行即可。
一個(gè)靜態(tài)方法,只能處理靜態(tài)數(shù)據(jù)(靜態(tài)屬性)

public static function sayCount () {
    echo self::$stu_count;
    echo "run";
}

PHP中特殊的方法訪問(wèn)問(wèn)題

靜態(tài)方法應(yīng)該類(lèi)來(lái)調(diào)用,非靜態(tài)方法,應(yīng)該對(duì)象調(diào)用。
但是:
無(wú)論靜態(tài)還是非靜態(tài),都可以使用類(lèi)來(lái)訪問(wèn)。
不過(guò)如果類(lèi)靜態(tài)調(diào)用一個(gè)非靜態(tài)方法,會(huì)報(bào)告一個(gè)strict standards 語(yǔ)法不標(biāo)準(zhǔn)的錯(cuò)誤。
對(duì)象也可以都調(diào)用

Class Student {

    public function fn1 () {
        echo "fn1";
    }
    
    public static function  fn2 () {
        
        echo "fn2";
        
    }
    
}

$stu1 = new Student();

Student::fn1();
Student::fn2();

$stu1->fn1();
$stu1->fn2();

區(qū)別就在于$this上
只有在使用對(duì)象調(diào)用非靜態(tài)方法時(shí),才可以使用方法內(nèi)的$this;
靜態(tài)方法,無(wú)論如何也不能對(duì)$this做處理
而非靜態(tài)方法,只有確定了對(duì)象,才能確定$this的值

類(lèi)常量

類(lèi)中,保存運(yùn)行運(yùn)行周期內(nèi),不變的數(shù)據(jù)。就是常量。

定義
const 關(guān)鍵字
const 常量名 = 常量值
沒(méi)有訪問(wèn)修飾限定符.

const PI = 3.14;

訪問(wèn)
類(lèi)::常量名
把屬性值,固定值,定義成常量。

self::PI;

常見(jiàn),類(lèi)中 屬性的選項(xiàng), 多定義成 常量。

類(lèi)中可以定義的成員一共有
常量,靜態(tài)屬性,靜態(tài)方法,非靜態(tài)屬性,非靜態(tài)方法
除了以上5個(gè),類(lèi)中,不能直接出現(xiàn)其他語(yǔ)句,例如echo的執(zhí)行性語(yǔ)句,var_dump(), 等等
簡(jiǎn)化一點(diǎn):常量,屬性,方法

$this 表示當(dāng)前對(duì)象
永遠(yuǎn)表示$this所在類(lèi)的對(duì)象么?
不是,因?yàn)?this的值,不取決于$this所在的類(lèi),而是$this所在方法在被調(diào)用時(shí)執(zhí)行對(duì)象(執(zhí)行環(huán)境)。

方法的執(zhí)行環(huán)境(context),當(dāng)前方法是在哪個(gè)對(duì)象的環(huán)境下執(zhí)行,方法在哪個(gè)對(duì)象的環(huán)境下執(zhí)行,該方法內(nèi)的$this 就表示哪個(gè)對(duì)象。
執(zhí)行環(huán)境向下環(huán)境.

繼承和重寫(xiě) 繼承

一個(gè)對(duì)象擁有或者使用另一個(gè)對(duì)象的成員信息,稱(chēng)之為這個(gè)對(duì)象繼承自另一個(gè)對(duì)象。

PHP中,通過(guò)在類(lèi)上,使用特殊的操作達(dá)到目的。
繼承是對(duì)象的概念,只不過(guò)語(yǔ)法上面要通過(guò)類(lèi)來(lái)實(shí)現(xiàn)。

通過(guò)在在定義類(lèi)時(shí),利用extends 來(lái)指明當(dāng)前類(lèi)的對(duì)象 , 繼承那個(gè)類(lèi)的對(duì)象。

class C {
    
    public $p_c = "value C";
    
}

class D extends C {
    public $p_d = "value D";
}

$d = new D();

var_dump($d->p_d);
var_dump($d->p_c);

繼承,指的是兩個(gè)對(duì)象之間,那么哪有這兩個(gè)對(duì)象?

class C {
    
    public $p_c = "value C";
    
}

class D extends C {
    public $p_d = "value D";
}

$d = new D();

var_dump($d instanceof D);  // true

var_dump($d instanceof C);  // true

相關(guān)概念
class D extends C {}
D 類(lèi)對(duì)象 繼承自 C 類(lèi)對(duì)象
父類(lèi):被繼承的類(lèi),C類(lèi)
子類(lèi):需要繼承的類(lèi),D類(lèi)

功能上:
基類(lèi):C類(lèi)是D類(lèi)的基類(lèi)
擴(kuò)展類(lèi):D類(lèi)是C類(lèi)的擴(kuò)展類(lèi)

繼承概念體現(xiàn)在對(duì)象上,語(yǔ)法體現(xiàn)在類(lèi)上。
語(yǔ)法意義就是,面向?qū)ο笳Z(yǔ)法中的,代碼的重用

PHP是單繼承
單繼承,一個(gè)類(lèi)只能繼承自另一個(gè)類(lèi),不能同時(shí)繼承多個(gè)類(lèi)。但是一個(gè)類(lèi)可以被多個(gè)類(lèi)繼承。

繼承的目的:
在于擴(kuò)展,或使用某個(gè)類(lèi)已經(jīng)存在的操作和數(shù)據(jù)。
繼承,在編程上,可以是理解成OOP代碼的共用。

重寫(xiě)override

只有發(fā)生在繼承上,才會(huì)出現(xiàn),是一個(gè)現(xiàn)象。
如果子類(lèi),與父類(lèi),出現(xiàn)同名的成員(屬性方法),則在實(shí)例化子類(lèi)對(duì)象時(shí),只會(huì)得到子類(lèi)中定義的成員,稱(chēng)之為重寫(xiě)。

成員沖突
繼承時(shí),如果發(fā)生成員沖突,PHP的處理方式,為重寫(xiě)。就是子類(lèi)同名成員會(huì)覆蓋父類(lèi)的同名成員。不能看到父類(lèi)的成員。

class P {
    public $name = "p";
    public function sayNmae () {
        echo "parent::name", $this->name;
    }
}    

class C extends P {
    public $name = "C";
    public function sayName () {
        echo "self::name",$this->name;
    }
}

$obj = new C();
echo $obj->name; // C
echo "
"; $obj->sayName(); // self::nameC

某些情況下,重寫(xiě)時(shí)一定發(fā)生的,例如構(gòu)造等。
如果需要,強(qiáng)制執(zhí)行被重寫(xiě)的父類(lèi)方法,可以顯式的使用父類(lèi)來(lái)調(diào)用相應(yīng)的父類(lèi)方法即可。

public function __construct () {
    P::__construct();
}

可以使用一個(gè)關(guān)鍵字,在類(lèi)內(nèi),代替當(dāng)前類(lèi)的父類(lèi)。
parent 關(guān)鍵字,代替父類(lèi)。
一旦重寫(xiě),父類(lèi)代碼就不會(huì)在執(zhí)行了。

P::__construct();
parent::__construct();  

如果說(shuō)父類(lèi)的構(gòu)造需要相應(yīng)的參數(shù),則需要將再調(diào)用時(shí),將父類(lèi)的構(gòu)造方法需要的參數(shù),也傳遞到方法內(nèi)。

class GoodsBook extends Goods {
    
    public $page;
    public function __construct ( $name, $price, $pages ) {
        
        parent::__constuct($name, $price);
        
        $this->pages = $pages;
        
    }
    
}

一般2到3層的繼承,就基本上可以

instanceof 操作符

用于判斷一個(gè)對(duì)象是否是某個(gè)類(lèi)的實(shí)例

$this的確定

只有在使用對(duì)象調(diào)用非靜態(tài)方法時(shí),才可以使用$this!

哪個(gè)對(duì)象調(diào)用方法,方法內(nèi)$this就是那個(gè)對(duì)象。

對(duì)象環(huán)境,是可以向下傳遞。

如果當(dāng)前方法內(nèi),已經(jīng)確定了對(duì)象環(huán)境。在該方法內(nèi),如果出現(xiàn)了靜態(tài)調(diào)用非靜態(tài)方法,此時(shí)當(dāng)前的對(duì)象環(huán)境,會(huì)傳遞到靜態(tài)方法調(diào)用的非靜態(tài)方法中。

class A {
    public function in_a () {
        var_dump($this);
    }
}

class B {
    public function in_b () {
        var_dump($this);  // B 實(shí)例化對(duì)象
        echo "
"; A::in_a(); // B 實(shí)例化對(duì)象 } } $obj = new B(); $obj->in_b();
PHP連接MySql 設(shè)置屬性和連接方法

構(gòu)造方法內(nèi),使用數(shù)組作為參數(shù),如果參數(shù)過(guò)多,便于管理。
利用參數(shù),為對(duì)象屬性進(jìn)行賦值
常見(jiàn)的,在實(shí)際操作中:為屬性設(shè)置默認(rèn)值。如果用戶在實(shí)例化時(shí),傳遞了屬性參數(shù),則使用用戶傳遞的,否則使用默認(rèn)值。

// $params Array
public function __construct ( $params ) {
    
    $this->host = isset($params["host"]) ? $params["host"] : "127.0.0.1";
    $this->port = isset($params["port"]) ? $params["port"] : "3306"; 
    $this->user = isset($params["user"]) ? $params["user"] : "root";
    $this->pass = isset($params["pass"]) ? $params["pass"] : "";
    $this->charset = isset($params["charset"]) ? $params["charset"] : "utf8";
    $this->dbname = isset($params["dbname"]) ? $params["dbname"] : "";
    $this->prefix = isset($params["prefix"]) ? $params["prefix"] : "";
            
}
連接

應(yīng)該在構(gòu)造方法內(nèi)完成
要求,一個(gè)功能,盡量使用一個(gè)方法獨(dú)立完成,一個(gè)大的功能,是由多個(gè)小功能組合起來(lái)。

// 連接數(shù)據(jù)庫(kù)
public function connect () {
    mysql_connect("$this->host:$this->port",$this->user,$this->pass);    
}  

為當(dāng)前的功能類(lèi),增加一個(gè)屬性,保存這個(gè)鏈接資源

// 運(yùn)行時(shí)生成的信息
public $link;

在連接成功后,為屬性賦值
連接失敗,給出提示

public function connect () {
        
    if ( $link = mysql_connect("$this->host:$this->port",$this->user,$this->pass) ) {
    
        $this->link = $link;
        
    } else {
        
        echo "連接失敗";
        exit;
        
    }
        
}
設(shè)置字符集,提取執(zhí)行SQL

設(shè)置字符集

// 設(shè)置字符集
public function setCharset () {
    $query = "set names $this->charset";
    
    if ( mysql_query($query) ) {
        
        // 成功
        
    } else {
        
        // 失敗
        echo "字符串設(shè)置失敗";
        exit;
        
    }
    
}

執(zhí)行sql語(yǔ)句

// 執(zhí)行SQL語(yǔ)句
public function query ( $query ) {
    
    if ( $reslut = mysql_query($query,$this->link) ) {
        
        // 執(zhí)行成功
        
        return $reslut;
        
    } else {
        
        // 執(zhí)行錯(cuò)誤 ,給出提示
        echo "SQL執(zhí)行錯(cuò)誤,錯(cuò)誤信息:
"; echo "出錯(cuò)的SQL為:", $query ,"
link), "
"; echo "錯(cuò)誤的信息為:", mysql_error($this->link), "
"; // 簡(jiǎn)單錯(cuò)誤處理,一旦出錯(cuò),直接停止掉腳本執(zhí)行 die; // 如果在完整的處理過(guò)程中, 出錯(cuò)應(yīng)該余下代碼繼續(xù)執(zhí)行 // 需要判斷是否執(zhí)行成功 ,返回false return false; } }

"127.0.0.1","port","3306","user",);
    public function __construct( $params ){

      //對(duì)屬性初始化
      //如果配置項(xiàng)選項(xiàng)存在,則使用用戶的,否則使用默認(rèn)的。
      $this->host = isset( $params["host"] ) ? $params["host"] : "127.0.0.1" ;            
      $this->port = isset( $params["port"] ) ? $params["port"] : "3306";            
      $this->user = isset( $params["user"] ) ? $params["user"] : "root";            
      $this->pass = isset( $params["pass"] ) ? $params["pass"] : "";            
      $this->charset = isset( $params["charset"] ) ? $params["charset"] : "utf8";            
      $this->dbname = isset( $params["dbname"] ) ? $params["dbname"] : "";            
      $this->prefix = isset( $params["prefix"] ) ? $params["prefix"] : "";

      //連接
      $this->connect();

      //設(shè)置字符集
      $this->setCharset();

      //選擇默認(rèn)數(shù)據(jù)庫(kù)
      $this->selectDB();

    }


    // 連接數(shù)據(jù)庫(kù)服務(wù)器
    public function connect(){

      if( $link = mysql_connect("$this->host:$this->port",$this->user,$this->pass) ){

        //連接成功
        $this->link = $link;

      } else {

        //連接失敗
        echo "連接失敗 !";
        exit;
      }

    }

      
    // 設(shè)置字符集    
    public function setCharset(){

        $query = "set names $this->charset";
        $this->query($query);
    }   

    // 選擇默認(rèn)數(shù)據(jù)庫(kù)
    public function selectDB(){

        $query = "use $this->dbname";

        $this->query($query);

    } 


     // 執(zhí)行SQL語(yǔ)句 
     // @param  $query string 需要執(zhí)行的SQL語(yǔ)句.
     // @return mixed 成功返回資源結(jié)果集或者true. 失敗返回false. 
    public function query( $query ){

      if( $result = mysql_query($query,$this->link) ){

          //執(zhí)行成功
          return $result;
      } else {

          //執(zhí)行失敗
          //給出錯(cuò)誤提示
          echo "SQL執(zhí)行出錯(cuò),錯(cuò)誤信息如下:
"; echo "出錯(cuò)的SQL語(yǔ)句為:",$query,"
"; echo "錯(cuò)誤的代碼為:",mysql_errno($this->link),"
"; echo "錯(cuò)誤的信息為:",mysql_error($this->link),"
"; //簡(jiǎn)單錯(cuò)誤處理,一旦出錯(cuò),直接停止腳本執(zhí)行. die; //如果再完整的處理過(guò)程中,出錯(cuò)應(yīng)該余下的代碼繼續(xù)執(zhí)行。 //需要判斷是否執(zhí)行成功,返回false. // return false; } } } $db = new MYSQLDB( array("host"=>"127.0.0.1","port"=>3306,"user"=>"root","pass"=>"") ); var_dump($db); ?>
訪問(wèn)控制說(shuō)明 訪問(wèn)修飾限定符

public , protacted, private
用于描述,一個(gè)成員(屬性,方法)在哪里才能被訪問(wèn)的。

php5中,要求所有的成員(屬性和方法)都應(yīng)該受訪問(wèn)修飾的控制,聲明時(shí),前面都應(yīng)該存在訪問(wèn)修飾限定符

存在例外,為了兼容.

在聲明屬性時(shí),可以使用特殊的 var 關(guān)鍵字.相當(dāng)于使用public來(lái)聲明.

class Student {
    var $stu_id;
} 

方法中,聲明時(shí),可以省略訪問(wèn)修飾限定符.相當(dāng)于public.

class Student {
    function sayCount () {}
}

public ,公共的,成員在類(lèi)內(nèi),繼承鏈上類(lèi)內(nèi),和類(lèi)外都可以訪問(wèn)到(任何地方)
protacted , 保護(hù)的,就是類(lèi)內(nèi)和繼承鏈上的類(lèi)內(nèi) 都可以訪問(wèn).
private , 私有的, 類(lèi)內(nèi).

PHP是采用類(lèi)的概念,進(jìn)行成員的限制訪問(wèn)的。
PHP將訪問(wèn)的代碼,分成三大區(qū)域:類(lèi)內(nèi),類(lèi)外,繼承鏈上的類(lèi)內(nèi)。
類(lèi)內(nèi): 定義該成員所在類(lèi)的內(nèi)部.
繼承鏈上的類(lèi)內(nèi)
類(lèi)外

類(lèi)外訪問(wèn):只有公共可以訪問(wèn)

類(lèi)內(nèi)訪問(wèn):類(lèi)中所定義的方法內(nèi)

所有的限定都可以

繼承鏈上的類(lèi)內(nèi):

保護(hù)的和公共的可以被訪問(wèn),而私有的不可以被訪問(wèn).

根據(jù):成員在哪里定義 與 成員在哪里訪問(wèn) 來(lái)決定 類(lèi)內(nèi) , 類(lèi)外 還是 繼承鏈上的類(lèi)內(nèi)。

注意
受保護(hù),繼承鏈上的類(lèi)內(nèi)
父類(lèi)內(nèi)定義,子類(lèi)內(nèi)訪問(wèn). 反過(guò)來(lái),子類(lèi)內(nèi)定義父類(lèi)內(nèi)可以訪問(wèn).

私有成員的問(wèn)題
出現(xiàn)在 私有屬性 的重寫(xiě)上
PHP會(huì)記錄所有的私有屬性,同時(shí)會(huì)記錄私有屬性所在的類(lèi),在不同類(lèi)內(nèi)訪問(wèn)不同的私有屬性時(shí)是不同的。而, 公共的和 受保護(hù)的, 則只會(huì)記錄一次,明顯的被重寫(xiě)了;
寫(xiě)繼承的時(shí)候,如果是有屬性被重寫(xiě)了,要注意到,當(dāng)前所訪問(wèn)的私有屬性是哪一個(gè)私有屬性.

私有成員不能被重寫(xiě)。意味著,在相應(yīng)的私有屬性定義在類(lèi)中,才能訪問(wèn)到相應(yīng)的私有屬性。

建議是:如果需要通過(guò)繼承,就使用保護(hù)的,少用私有的。在沒(méi)有繼承時(shí),盡量使用私有的。

重寫(xiě)的問(wèn)題,要先明確訪問(wèn)的究竟是哪里所定義的。

在重寫(xiě)時(shí),如果重寫(xiě)成員的訪問(wèn)級(jí)別不一致。子類(lèi)的級(jí)別比父類(lèi)的級(jí)別,相等或者弱,可以。強(qiáng),不行。

封裝

怎么使用訪問(wèn)修飾,如何選擇

原則:盡量提高,類(lèi)對(duì)其成員的控制能力. 能用private,盡量使用private,能用protected就不用public.
一個(gè)原則,盡量體現(xiàn)封裝性。封裝性,指的是,盡量隱藏內(nèi)部實(shí)現(xiàn),而僅僅開(kāi)發(fā)外部操作接口!
語(yǔ)法上,就是,將不需要外部使用的屬性,方法,都私有化(保護(hù)化),而僅僅留下一些必要的公共方法!

選擇訪問(wèn)修飾限定符,體現(xiàn)oop思想的封裝性的特點(diǎn).
封裝性:隱藏對(duì)象的內(nèi)部實(shí)現(xiàn)細(xì)節(jié),只提供外部操作方法。
對(duì)象的外部操作方法,稱(chēng)之為對(duì)象的接口(interface). 接口在語(yǔ)法上,就是一些公共的方法.
封裝:只有操作接口可以被看到,內(nèi)部實(shí)現(xiàn)都被隱藏.

經(jīng)典的:幾乎所有的屬性和大部分的方法都是私有(如果有繼承的話,會(huì)有受保護(hù)).只有一些供外部調(diào)用者使用的方法,是公共的.

類(lèi): 繼承和實(shí)例化
類(lèi): 調(diào)用其靜態(tài)成員
類(lèi): 作為其他類(lèi)的基礎(chǔ)類(lèi),被繼承
兩大功能:實(shí)例化對(duì)象, 基礎(chǔ)類(lèi)被繼承

抽象類(lèi): 只能被繼承,不能被實(shí)例化對(duì)象
final類(lèi): 只能被實(shí)例化,不能被繼承

final類(lèi)

該類(lèi),只能被實(shí)例化對(duì)象不能用于被繼承。
設(shè)計(jì)時(shí),該類(lèi)不能再擴(kuò)展,就應(yīng)該通過(guò)語(yǔ)法,final限制,其它用戶擴(kuò)展該類(lèi).
最終,在繼承鏈條上, 最末的一個(gè)類(lèi),其下不能再出現(xiàn)子類(lèi),意味著不能被繼承。

定義
在 class 前 加 final關(guān)鍵字,即可.

final class GoodsBook extends Goods {}

如果繼承該類(lèi),會(huì)報(bào)錯(cuò)

因此,final 類(lèi)的作用,是在語(yǔ)法上,人為的限定哪些類(lèi)不能被繼承.

final 關(guān)鍵字的另一個(gè)用法, 用于限制方法,在所屬類(lèi),被繼承時(shí),該方法不能被重寫(xiě).

// 所有商品輸出價(jià)格方式一致
final public function sayPrice() {
    echo "¥",$this->shop_price;
}
抽象類(lèi)abstract

有一種類(lèi),只能被繼承,不能被實(shí)例化對(duì)象。原因就是這個(gè)類(lèi)的定義不完整. (有了一半的藏寶圖,需要找到其它的藏寶圖,補(bǔ)充完整) 為什么會(huì)不完整? 因?yàn)镻HP支持定義一種,只有方法的聲明部分,而沒(méi)有方法的實(shí)現(xiàn)部分的不完整方法。(類(lèi)所包含的元素,不完整,可以不完整的是方法)。

如果某個(gè)類(lèi),包含了這種不完整的方法,就不是一個(gè)完整的類(lèi),就不能實(shí)例化對(duì)象!

不完整的類(lèi), 稱(chēng)之為 抽象類(lèi). abstract class

所包含的不完整的方法,稱(chēng)之為:抽象方法. abstract method

定義
包含了抽象方法的類(lèi),就是抽象類(lèi)

語(yǔ)法
定義抽象方法,利用一個(gè)叫 abstruct 的關(guān)鍵字,告知PHP某個(gè)方法時(shí)一個(gè)抽象方法,沒(méi)有方法體

abstract public funciton sayName();  // 要注意分號(hào)

定義一個(gè)抽象類(lèi)
如果一個(gè)類(lèi)包含了抽象方法,也就是抽象類(lèi),因此也需要使用 abstruct 關(guān)鍵字聲明.

沒(méi)有實(shí)例化的能力
實(shí)例化報(bào)錯(cuò)
只有被繼承的能力
如果繼承某個(gè)抽象類(lèi)的類(lèi)是非抽象類(lèi)的話,就一定要將不完整的抽象方法實(shí)現(xiàn)。否則該類(lèi)也應(yīng)該是一個(gè)抽象類(lèi).

抽象類(lèi)的具體功能
1:限制子類(lèi)的結(jié)構(gòu)

由于抽象類(lèi),只能被繼承,而且如果其子類(lèi)不是一個(gè)抽象類(lèi)的話,要求必須實(shí)現(xiàn)抽象類(lèi)所定義的抽象方法,因此抽象類(lèi)的功能也可以理解成,用于限制其子類(lèi)(擴(kuò)展類(lèi))的結(jié)構(gòu).

就可以保證,同一系列的處理類(lèi),所擁有的結(jié)構(gòu)是一致的。將來(lái)可以實(shí)現(xiàn)無(wú)縫對(duì)接,任意切換(熱插拔) 。

2:可以限制

方法名,參數(shù)個(gè)數(shù).

訪問(wèn)修飾控制.
擴(kuò)展類(lèi)(子類(lèi))的權(quán)限限制,弱于抽象類(lèi)

抽象類(lèi)功能
在可以為子類(lèi)(擴(kuò)展類(lèi))提供共用操作的同時(shí),限制子類(lèi)(擴(kuò)展類(lèi))所擁有的方法的結(jié)構(gòu).
犧牲掉了實(shí)例化對(duì)象的功能.

接口 interface

一個(gè)對(duì)象的封裝,分為兩大部分

內(nèi)部實(shí)現(xiàn)

就是操作接口

PHP中,可以規(guī)定,一個(gè)對(duì)象應(yīng)該具有哪些公共的外部操作,使用interface來(lái)規(guī)定

公共的方法就是接口
用于規(guī)定一個(gè)對(duì)象應(yīng)該擁有哪些公共的操作方法(接口),這個(gè)東西也叫接口(公共操作方法的集合).
接口(interface 結(jié)構(gòu),公共方法的集合)

公共方法(接口方法)
定義:用于限定某個(gè)對(duì)象所必須擁有的公共操作方法的一種結(jié)構(gòu),稱(chēng)之為接口(interface).
就是用于限制公共方法。

語(yǔ)法:
定義這個(gè)接口結(jié)構(gòu),使用interface 關(guān)鍵字.接口定義的都是公共的方法

interface 接口名 {
    公共操作方法列表
}

interfece I_Goods {
    public function sayName();
    public function sayPrice();
}

注意:
接口方法,必須都是公共的
接口內(nèi)只能有公共方法,不能存在成員變量屬性

interfece I_Goods {
    public $goods_name; //報(bào)錯(cuò)
    public function sayName();
    public function sayPrice();
}  

接口內(nèi),只能含有未被實(shí)現(xiàn)的方法,也叫抽象方法,但是不用abstract關(guān)鍵字().
如果是一個(gè)完整方法,會(huì)報(bào)錯(cuò)。

使用接口
限制對(duì)象的必要的公共操作
類(lèi)實(shí)現(xiàn)接口 (實(shí)現(xiàn)--把你想做的事完成). 利用關(guān)鍵字, implements;

class Goods implements I_Goods {}

這樣,實(shí)現(xiàn)該接口的類(lèi),必須實(shí)現(xiàn)接口內(nèi)所有的抽象方法。而且可以肯定,該方法一定是公共的外部操作方法

// 定義接口 
interface I_Goods {
    
    public function sayName();
    public function sayPrice(); 
    
}

// 實(shí)現(xiàn)接口
class Goods implements I_Goods {
    
    public $goods_name;
    public $shop_price;
    public function __construct ( $name, $price ) {
                
        $this->goods_name = $name;
        $this->shop_price = $price;    
        
    }
    
    public function sayName () {
        echo $this->goods_name;
    }
    public function sayPrice () {
        
    }
}

$goods = new Goods("php", 234);
$goods->sayName();
$goods->sayPrice();

類(lèi)似于抽象類(lèi),比較與接口的區(qū)別:
抽象類(lèi)與普通類(lèi)之間是繼承關(guān)系
普通類(lèi)繼承抽象了,第一可以得到抽象類(lèi)中的已有的常規(guī)成員,第二才需要實(shí)現(xiàn)抽象方法(也不一定是public)

接口與普通類(lèi)之間是實(shí)現(xiàn)關(guān)系
普通類(lèi)實(shí)現(xiàn)了接口,只能將其沒(méi)有實(shí)現(xiàn)的公共方法實(shí)現(xiàn)

接口只用于定義 公共的方法。 而抽象類(lèi),什么都可以有。

多實(shí)現(xiàn)

上面的功能,理論上講,可以通過(guò)抽象類(lèi)完成。 但是抽象類(lèi),不專(zhuān)業(yè)
接口專(zhuān)業(yè)體現(xiàn)在實(shí)現(xiàn)上,因?yàn)镻HP支持多實(shí)現(xiàn),而僅支持單繼承.

class Goods implements I_Goods, I_Shop {
    
}

繼承和實(shí)現(xiàn)區(qū)別
繼承:體現(xiàn)的是將別的對(duì)象已經(jīng)存在的東西,拿來(lái)自己用
實(shí)現(xiàn):將某個(gè)地方的規(guī)定,自己來(lái)完成

接口之間,也可以繼承

interface I_Shop extend I_Goods {
    public function saySafe();    
}

抽象類(lèi) pk 接口
繼承 pk 實(shí)現(xiàn)

PHP對(duì)接口的支持,可以定義常量

interface I_Shop extend I_Goods {
    const PAI = 3.14;
}    

通過(guò)類(lèi)去訪問(wèn)

    
class Goods implements I_Shop {}

echo Goods::PAI; 

辨別
接口是不是類(lèi) ?
接口不是類(lèi),接口就是獨(dú)立的一種結(jié)構(gòu),適用于限制類(lèi)的結(jié)構(gòu)。但是可以理解成"接口類(lèi)似于一個(gè)所有的方法都是公共的抽象方法,而且沒(méi)有其它成員的抽象類(lèi)",并不是一個(gè)概念。
class_exists(); 判斷一個(gè)類(lèi)是否存在?

繼承應(yīng)用 表操作模型

項(xiàng)目中操作數(shù)據(jù)庫(kù)的典型模式: 數(shù)據(jù)操作模型(model).

常見(jiàn)的操作
PHP項(xiàng)目中,由于不同的數(shù)據(jù)實(shí)體對(duì)應(yīng)的業(yè)務(wù)邏輯是不同的,通常的操作數(shù)據(jù)的方法:為每張表創(chuàng)建一個(gè)操作對(duì)象

class BaseTable {}

class GoodsTable extends BaseTable {}

class CrtegoryTable extends BaseTable {}

如果兩個(gè)類(lèi)有具體的關(guān)系,使用繼承.

聚合

如果是多個(gè)類(lèi)需要使用另一個(gè)類(lèi),所提供的功能,還有一種方式,稱(chēng)之為聚合.

class MySQLDB {
    public function query () {

    }
}

class BrandTable {
    public $db;
    public function __construct () {
        $this->db = new MysqlDB();
        $this->db->query();
    }
}

$brand = new BarndTable();
$brand->db;

如果,BrandTbale 類(lèi) 對(duì)象,需要使用MySQLDB類(lèi)對(duì)象的相應(yīng)功能,可以BrandTable對(duì)象內(nèi),增加一個(gè)屬性保存MySQLDB類(lèi)對(duì)象。打到 BarndTable使用MySQLDB 對(duì)象的功能目的
這種方式,稱(chēng)之為 對(duì)象的聚合。

既然聚合繼承 都可以達(dá)到 共用一個(gè)類(lèi)功能的目的,使用的標(biāo)準(zhǔn)
如果說(shuō)兩個(gè)類(lèi)之間存在邏輯關(guān)系上的必然聯(lián)系,就建議使用繼承。
反之,如果是邏輯上,一個(gè)對(duì)象使用另一個(gè)對(duì)象,此時(shí)應(yīng)該使用對(duì)象間的聚合。

優(yōu)劣性
使用繼承,可以增加類(lèi)之間的聯(lián)系,增加關(guān)聯(lián)性。
而使用聚合,可以降低類(lèi)之間的關(guān)聯(lián)性,可以降低耦合性!

自動(dòng)加載機(jī)制

保存類(lèi)的方法:
將類(lèi)的定義代碼,放置在一個(gè)獨(dú)立的文件中. 如果需要該類(lèi),則直接調(diào)用.

為了識(shí)別,某個(gè)類(lèi)定義文件,常見(jiàn)的,類(lèi)定義文件的命名方式為:
類(lèi)名.class.php

使用時(shí)引入:

require("./MySQLDB.php");

思考:
如果項(xiàng)目中,多處使用OOP,導(dǎo)致整個(gè)項(xiàng)目中,出現(xiàn)多個(gè) xxx.class.php 文件,每當(dāng)需要都需要引入 ?

使用自動(dòng)加載,按需引入類(lèi)文件
需要解決的問(wèn)題:
1,什么時(shí)候需要類(lèi)?
實(shí)例化時(shí),靜態(tài)調(diào)用時(shí),一個(gè)類(lèi)被繼承時(shí)如果使用其子類(lèi)時(shí)。
2,在需要時(shí),應(yīng)該主動(dòng)require 系列的代碼, 才可能加載成功,如何做到需要自動(dòng)執(zhí)行某段代碼?
3,需要的是類(lèi),而載入的是文件,需要解決如何通過(guò) 類(lèi) 來(lái)確定 類(lèi)文件的所在文件.

PHP解決了前2個(gè)問(wèn)題,需要解決第三個(gè)問(wèn)題。
PHP提供了一個(gè)機(jī)制(功能),可以在需要某個(gè)類(lèi),但是沒(méi)有載入這個(gè)定義類(lèi)時(shí).會(huì)自動(dòng)調(diào)用某個(gè)函數(shù)。并同時(shí)將當(dāng)前所需要的類(lèi)名,作為參數(shù)傳遞到這個(gè)自動(dòng)調(diào)用的函數(shù)內(nèi)。
PHP提供一個(gè)時(shí)機(jī),完成自動(dòng)加載。
這個(gè)函數(shù)默認(rèn)不存在,需要用戶自己定義。 函數(shù)名為 __autoload();

function __autolaod ( $class_name ) {
    var_dump($class_name);
    require $class_name.".class.php";
}

一旦函數(shù)存在,在特定情況(需要類(lèi)但是沒(méi)有找到),則PHP內(nèi)部會(huì)自動(dòng)調(diào)用__autoload().執(zhí)行在函數(shù)體定義的函數(shù),從而完成加載類(lèi)所在的文件。

分工:
用戶腳本:定義函數(shù),接收需要的類(lèi)名作為參數(shù),函數(shù)需要實(shí)現(xiàn)通過(guò)類(lèi)名找到類(lèi)所在的文件,將其載入即可!
PHP核心(Zend Engine):判斷是否需要類(lèi),并且判斷該類(lèi)是否已經(jīng)載入了,如果需要但是沒(méi)有載入,則嘗試調(diào)用用戶定義的__autoload()函數(shù),并將需要的類(lèi)名傳遞即可!

__autoload 函數(shù)名得到是類(lèi)名
而載入的是類(lèi)文件定義的文件。
因此,自動(dòng)加載機(jī)制的前提:必須要能夠通過(guò)類(lèi)名,推導(dǎo)出,類(lèi)所在的文件才可以。(定義類(lèi)文件時(shí),要有規(guī)律)

注意:
PHP提供了加載代碼的執(zhí)行時(shí)機(jī)。用戶腳本,需要完成加載代碼,其中核心任務(wù)是,通過(guò)所得到的類(lèi)名,找到類(lèi)定義所在的文件。

對(duì)象序列化

序列化,反序列化(串行化,反串行化)

數(shù)據(jù)持久化
在數(shù)據(jù)保存,面臨一個(gè)問(wèn)題:數(shù)據(jù)格式。

PHP的數(shù)據(jù)有八種類(lèi)型之多,文件只能存儲(chǔ)字符串。

一旦數(shù)據(jù)類(lèi)型不是字符串類(lèi)型。就會(huì)導(dǎo)致數(shù)據(jù)不能原樣保存,不能取得原始數(shù)據(jù)。
如何解決
任何形式的數(shù)據(jù),都可以存儲(chǔ)到文件中,并且,在取出來(lái)時(shí),原樣得到數(shù)據(jù)。
在保存,與讀取時(shí),對(duì)數(shù)據(jù)進(jìn)行轉(zhuǎn)換與反轉(zhuǎn)換。

序列化
serialize();
原始數(shù)據(jù)轉(zhuǎn)成能夠記錄的原始數(shù)據(jù)信息的字符串

反序列化
unserialize();
通過(guò)序列化的字符串結(jié)果,將原始數(shù)據(jù)還原!

只有在涉及到,數(shù)據(jù)需要被存儲(chǔ),或者 傳輸時(shí), 需要對(duì)數(shù)據(jù)進(jìn)行序列化。

注意的數(shù)據(jù)類(lèi)型都可以被序列化與反序列外。資源是例外!

對(duì)象的序列化與反序列化

在對(duì)象被反序列化時(shí),需要找到當(dāng)前對(duì)象所屬的類(lèi)才可以被完美的反序列化,如果不能找到屬于的類(lèi),那么會(huì)變成php內(nèi)置類(lèi):__PHP_Incompleta_Class(不完整類(lèi))的一個(gè)對(duì)象.
因此,只要在反序列話之前,將類(lèi)載入即可。

反序列化,也會(huì)觸發(fā)自動(dòng)加載機(jī)制。

在序列化時(shí),可以自定義需要序列化的屬性名單!

通過(guò)對(duì)象的特殊的方法 __sleep();
該方法會(huì)在對(duì)象被序列化時(shí),自動(dòng)調(diào)用,不需要參數(shù),返回一個(gè)數(shù)組,每個(gè)元素,表示一個(gè)屬性名,數(shù)組內(nèi)存在的屬性名,就會(huì)被序列化。反之則不會(huì)被序列化。

// 在序列化時(shí)被調(diào)用
// 用于負(fù)責(zé)指明那些屬性需要被序列化
// @return array

public function __sleep () {
    return array("host", "port", "user", "pass", "charset", "dbname");
}

在反序列化時(shí),可以自動(dòng)再次執(zhí)行某些代碼,從而完成某些資源的初始化!
通過(guò) 對(duì)象方法:__wakeup()方法
會(huì)在 對(duì)象被反序列過(guò)程中自動(dòng)調(diào)用,所負(fù)責(zé)的功能,執(zhí)行反序列話(醒來(lái)之后)的初始化工作!

// 在反序列化時(shí)調(diào)用
// 用于 對(duì)對(duì)象的屬性進(jìn)行初始化

public function __wakeup () {

    // 連接數(shù)據(jù)庫(kù)
    $this->connect();

    // 設(shè)置字符集
    $this->setCharset();

    // 設(shè)置默認(rèn)數(shù)據(jù)庫(kù)
    $this->selectDB();

}

PHP 自動(dòng)調(diào)用, 用戶腳本只需要定義。在特定的功能調(diào)用特定的方法。稱(chēng)之為:魔術(shù)方法。

單例模式

單例,單個(gè)實(shí)例。設(shè)計(jì)模式的一種,通過(guò)一種語(yǔ)法的設(shè)計(jì),保證類(lèi)(對(duì)象)上具有某些特征,這樣的一種語(yǔ)法實(shí)現(xiàn),就可以稱(chēng)之為設(shè)計(jì)模式。
其中,設(shè)計(jì)可以保證一個(gè)類(lèi),有且只有一個(gè)對(duì)象,這種設(shè)計(jì)模式就稱(chēng)之為單例模式。

單例模式的作用,單例的設(shè)計(jì),是適用于使用一個(gè)對(duì)象可以完成所有業(yè)務(wù)邏輯的類(lèi)

典型的實(shí)現(xiàn),在類(lèi)上,做限制:三私一公。
某個(gè)類(lèi)只要實(shí)例化一次就可以完成所有的業(yè)務(wù)邏輯!
但是實(shí)例化多次也可以。

顯然,應(yīng)該保證對(duì)象被實(shí)例化一次,從而節(jié)約資源空間!

MySQLDB類(lèi),如何設(shè)計(jì),從而達(dá)到保證該類(lèi) 有且只有一個(gè)對(duì)象.
原因:使用者,可以無(wú)限次的去實(shí)例化 這個(gè)類(lèi)。

三私一公
1:限制,用戶無(wú)限制執(zhí)行new
在實(shí)例化的過(guò)程中,需要執(zhí)行構(gòu)造方法,如果執(zhí)行不成功,那么實(shí)例化過(guò)程失敗。因此,將構(gòu)造方法,私有化(保護(hù)化),可以保證在類(lèi)外進(jìn)行實(shí)例化的工作都會(huì)失敗。

class MySQLDB {
    
    private function __construct () {
        
    } 
    
}

2,類(lèi),不能實(shí)例化了,不能再類(lèi)外實(shí)例化,可以在類(lèi)內(nèi)實(shí)例化,類(lèi)內(nèi)執(zhí)行new操作。

因此:在類(lèi)中,增加一個(gè)公共的靜態(tài)的方法,在方法內(nèi),執(zhí)行new實(shí)例化類(lèi)對(duì)象。

class MySQLDB {
    
    // 私有化構(gòu)造函數(shù)    
    private function __construct () {
        
    } 
    
    // 執(zhí)行new
    public static function getInstance () {
        return new MySQLDB();
    }
    
}

$db1 = MySQLDB::getInstance();

$db2 = MySQLDB::getInstance(); 

var_dump($db1, $db2);

3,可以無(wú)限制的調(diào)用getInstance得到任意多個(gè)對(duì)象!但是此時(shí)得到對(duì)象都需要經(jīng)過(guò) getInstance,可以在getInstance內(nèi),增加限制,使用戶得到對(duì)象的改變!

在實(shí)例化好對(duì)象后,將對(duì)象存起來(lái),下次再執(zhí)行時(shí),判斷是否已經(jīng)有保存的,有了,直接返回已經(jīng)存在的,沒(méi)有,實(shí)例化后,保存起來(lái),再返回!
增加一個(gè)私有的靜態(tài)屬性,在 getinstance內(nèi)做判斷

class MySQLDB {
    
    // 判斷是否實(shí)例化過(guò)
    public static $getinstance;
    
    // 私有化構(gòu)造函數(shù)    
    private function __construct () {
        
    } 
    
    // 執(zhí)行new
    public static function getInstance () {
        
        // 沒(méi)有實(shí)例化
        if ( !(self::$getinstance instanceof self) ) {
            
            self::$getinstance = new self;
            
        }
        
        return self::$getinstance;
        
    }
    
}

4:還可以通過(guò)克隆來(lái)得到新對(duì)象
需要私有化__clone()方法

// 私有化 __clone 方法
private function __clone () {
    
}

注意:?jiǎn)卫J絺鲄?wèn)題

在項(xiàng)目的設(shè)計(jì)層面解決單例的問(wèn)題

增加一個(gè)實(shí)例化的方法(函數(shù))
作用:用戶如果想要得到單例對(duì)象,就通過(guò)調(diào)用該函數(shù)完成!

function getInstace ( $class_name ) {
    
    static $objects = array();
    
    if ( !isset($objects[$class_name]) ) {
        
        $objects[$class_name] = new $class_name;
        
    }
    
    return $objects[$class_name];
    
}

優(yōu)點(diǎn):靈活,可以針對(duì)多個(gè)類(lèi)同時(shí)實(shí)現(xiàn)單例,而且,類(lèi)還可以回歸到非單例的效果。

重載overload

屬性重載 __set() __get()

傳統(tǒng)意義的重載,一個(gè)方法的多種狀態(tài),通常使用,參數(shù)類(lèi)型或者參數(shù)個(gè)數(shù)進(jìn)行區(qū)分,決定當(dāng)前使用那個(gè)函數(shù)。

PHP不支持同名方法。

PHP的重載:指的是對(duì)不可訪問(wèn)的成員的操作。
不可訪問(wèn)的成員: 指的是 不存在 , 或者是,由于訪問(wèn)修飾控制訪問(wèn)不到的。

// PHP允許為對(duì)象增加類(lèi)中沒(méi)有定義的屬性
class Student {
    public $stu_name;
    private $stu_id;
}

$stu = new Student();

var_dump($stu);

echo "
"; $stu->stu_gender = "male"; var_dump($stu);

// PHP對(duì)屬性除了增加,還支持刪除
class Student {
    public $stu_name;
    private $stu_id;
}

$stu = new Student();

$stu->stu_gender = "male";

unset($stu->stu_name);

var_dump($stu);

對(duì)類(lèi)后續(xù)進(jìn)行操作,用戶可以操作對(duì)象任意的修改對(duì)象的結(jié)構(gòu)。
PHP如何處理上面的情況,稱(chēng)之為重載(屬性的重新加載,成員的重新加載).

重載:對(duì)成員的重新加載

成員分為:屬性和方法,因此,php支持屬性重載 和 方法重載.

屬性重載

PHP對(duì),不可訪問(wèn)的屬性進(jìn)行操作處理方法,稱(chēng)之為屬性重載
PHP需要通過(guò)支持 魔術(shù)方法完成。
PHP在處理重載屬性時(shí),支持使用4個(gè)魔術(shù)方法,完成處理屬性重載的情況.

__set()

當(dāng)為不可訪問(wèn)的屬性賦值時(shí),會(huì)被自動(dòng)調(diào)用
會(huì)得到兩個(gè)參數(shù),當(dāng)前操作的屬性名,和屬性值!

// $p_name string 屬性名
// $p_value mixed 屬性值
public function __set ( $p_name, $p_value ) {
    
    // 實(shí)現(xiàn), 處理情況
    return ;

}

典型的,__set()的作用, 用于嚴(yán)格控制對(duì)象結(jié)構(gòu),和批量處理可以被修改的屬性。

// $p_name string 屬性名
// $p_value mixed 屬性值
public function __set ( $p_name, $p_value ) {
    
    // 實(shí)現(xiàn), 處理情況
    // 不可增加任何屬性, 但是可以對(duì) age 和 gender 做出修改
    $allow_preperties = array("s_age", "s_gender");

    if ( in_array($p_name, $allow_preperties) ) {
        $this->$p_name = $p_value; // 利用可變屬性,屬性名由變量代替
    }

}

$s = new Student();
$s->s_name = "天機(jī)老人";
$s->s_age = 87;

__get()

當(dāng)訪問(wèn)不可訪問(wèn)的屬性時(shí),會(huì)被自動(dòng)調(diào)用
需要的參數(shù)是:一個(gè),為當(dāng)前操作的屬性名

public function __get ( $p_name ) {
    
    // 讀取名字 性別
    if ( $p_name == "s_name" || $p_name == "s_gender" ) {

        return $this->$p_name; // 可變屬性

    } else {

        // 讀取年齡
        if ( $this->s_gender == "male" ) {

            return $this->s_age;    

        }

    }
}    

__unset()

刪除一個(gè)不可訪問(wèn)的屬性時(shí),可以自動(dòng)被調(diào)用!
需要一個(gè)參數(shù) 當(dāng)前操作的屬性名。
此時(shí)就可以利用業(yè)務(wù)邏輯完成 屬性的刪除處理!

public function __unset ( $p_name ) {
    
    if ( $cound )     {
        unset($this->$p_name);
    }

}

__isset()

判斷一個(gè)不可訪問(wèn)的屬性是否存在時(shí),被自動(dòng)調(diào)用
需要一個(gè)參數(shù),屬性名
注意,次函數(shù)需要返回true,或者false,表示屬性是否存在

public function __isset ( $p_name ) {
    
    if ( $p_name == "s_gender" ) {
        return true;
    } else {
        return false;
    }

}
方法重載

__call()

當(dāng)訪問(wèn)一個(gè)不可訪問(wèn)的對(duì)象方法時(shí),會(huì)觸發(fā)__call()的魔術(shù)方法!
需要的參數(shù)時(shí):
2個(gè)參數(shù),第一是當(dāng)前的方法名,第二是調(diào)用時(shí)使用的實(shí)參列表!

public function _call ( $m_name, $m_args ) {

    var_dump($m_name, $m_args);

}    

$s = new Student();
$s->sayName("zf", "php");

典型應(yīng)用
1,給出友好提示
2,執(zhí)行默認(rèn)操作

public function _call ( $m_name, $m_args ) {

    var_dump($m_name, $m_args);
    echo "執(zhí)行了默認(rèn)操作";
    $this->default_action();

}
    
public function default_action () {
    echo "這里是操作";
}    


$s = new Student();
$s->sayName("zf", "php");

static __callStatic()

與 __call類(lèi)似,當(dāng)靜態(tài)調(diào)用一個(gè)不可訪問(wèn)的方法時(shí),會(huì)自動(dòng)執(zhí)行!

public static function __callStatic ( $m_name, $m_args ) {
    var_dump( $m_name, $m_args );
}

Student::sayCount();

魔術(shù)方法
magic method

在特定的情況下,會(huì)被自動(dòng)調(diào)用的方法,通常負(fù)責(zé)完成某塊獨(dú)立的功能的方法稱(chēng)之為魔術(shù)方法!
特點(diǎn):1,需要用戶腳本定義,不定義不執(zhí)行!2,命名方式都是以__開(kāi)頭

__invoke()

將一個(gè)對(duì)象,當(dāng)作函數(shù)調(diào)用時(shí),會(huì)觸發(fā)該對(duì)象的__invoke()方法,由此方法,就可以調(diào)用,沒(méi)有該方法就不能調(diào)用!

__invoke是PHP實(shí)現(xiàn)匿名函數(shù) 不可或缺的部分!

也可以傳遞參數(shù),為對(duì)象傳遞參數(shù),就是為invoke魔術(shù)方法傳遞參數(shù)!

Closure 類(lèi)的對(duì)象(匿名函數(shù),閉包函數(shù)) 可以當(dāng)作函數(shù)調(diào)用,為什么我們自己定義的對(duì)象不可以當(dāng)做函數(shù)調(diào)用? 內(nèi)置的Closure 類(lèi)中有 __invoke();方法.

在將一個(gè)對(duì)象當(dāng)做函數(shù)調(diào)用時(shí), 會(huì)觸發(fā)該對(duì)象的 __invoke 方法, 如果方法不存在,對(duì)象不能當(dāng)做函數(shù)調(diào)用。反之 如果需要調(diào)用這個(gè)對(duì)象, 則可以為該對(duì)象增加 __invoke 方法使之執(zhí)行.

調(diào)用對(duì)象,其實(shí)就是調(diào)用該方法,可以接受參數(shù)!普通方法一樣處理即可.

魔術(shù)方法,只會(huì)負(fù)責(zé)某個(gè)特定的功能。當(dāng)某個(gè)特別的情況發(fā)生時(shí),才會(huì)調(diào)用相應(yīng)的魔術(shù)方法。
魔術(shù)方法可以沒(méi)有, 一旦有的話就會(huì)被調(diào)用.

__toString()
轉(zhuǎn)換到字符串的意思!
當(dāng)將對(duì)象當(dāng)作字符串使用時(shí),會(huì)自動(dòng)調(diào)用該對(duì)象的魔術(shù)方法!

存在toString 魔術(shù)方法,即可以完成轉(zhuǎn)換。
toString的返回值,就是轉(zhuǎn)換的結(jié)果,一般轉(zhuǎn)換對(duì)象的標(biāo)志性的屬性即可!

靜態(tài)延遲綁定

$this永遠(yuǎn)代表所在類(lèi)的對(duì)象?
不是
$this的值取決于$this所在方法的執(zhí)行對(duì)象環(huán)境.

self用于代表所在類(lèi)么?
是,永遠(yuǎn)代表所在類(lèi)的對(duì)象!
self 永遠(yuǎn)表示所在的類(lèi).
在那個(gè)類(lèi)中被定義,就應(yīng)該表示那個(gè)類(lèi).
因?yàn)閟elf,parent關(guān)鍵字,類(lèi)的編譯階段就確定了所代表的類(lèi).

class P {
    
    public static $where = "P static, 
"; public static function sayWhere () { echo self::$where; } } class C extends P { public static $where = "C static"; } echo P::sayWhere(); // P static, echo C::sayWhere(); // P static,

此時(shí),應(yīng)該是表示當(dāng)前類(lèi)的關(guān)鍵字,最好應(yīng)該在調(diào)用時(shí)決定最好!(self不能做到)

此時(shí),采用一個(gè)新的關(guān)鍵字,代表當(dāng)前類(lèi),與self不同,在于是 運(yùn)行時(shí)調(diào)用時(shí)決定,而不是在類(lèi)編譯時(shí)就確定好了的!
使用關(guān)鍵字:static

class P {
    
    public static $where = "P static, 
"; public static function sayWhere () { echo self::$where; } public static function sayW () { echo static::$where; } } class C extends P { public static $where = "C static,"; } echo P::sayWhere(); // P static, echo C::sayWhere(); // P static, echo "
"; echo P::sayW(); // P static, echo C::sayW(); // C static,

static關(guān)鍵字的功能
聲明靜態(tài)局部變量
聲明靜態(tài)成員
當(dāng)前類(lèi),運(yùn)行的當(dāng)前類(lèi)

類(lèi)中,可以表示類(lèi)的關(guān)鍵字:
self, 所在類(lèi)
static,調(diào)用類(lèi)
parent, 父類(lèi)

反射機(jī)制

常見(jiàn)的類(lèi)和對(duì)象操作函數(shù):

instanceof,判斷對(duì)象是否是某個(gè)類(lèi)的實(shí)例。
get_class(); // 返回對(duì)象的類(lèi)名
class_exists(); // 判斷一個(gè)類(lèi)是否存在
get_declared_classer() // 獲得當(dāng)前已經(jīng)存在的類(lèi). 包括預(yù)定義和用戶自定義的。
method_exists();   
property_exists();

相應(yīng)的魔術(shù)常量
__CLASS__ , 當(dāng)前類(lèi)名
__METHOD__, 當(dāng)前方法名

get_class_methods(); // 得到類(lèi)的方法
get_class_vars(); // 得到類(lèi)的屬性
可以得到類(lèi)內(nèi)的方法和屬性。
但是,得到的信息較少,只有名字,而且受到訪問(wèn)修飾符的限制。
如何才能夠詳細(xì)精確到類(lèi)中的結(jié)構(gòu)?
使用到反射機(jī)制

PHP提供的,用于獲得某個(gè)類(lèi),或者某種結(jié)構(gòu)(類(lèi),函數(shù),方法,屬性,參數(shù),擴(kuò)展....);
需要使用反射機(jī)制,反射機(jī)制時(shí)利用OOP的語(yǔ)法實(shí)現(xiàn)了。
反射機(jī)制提供了很多類(lèi),針對(duì)不同的結(jié)構(gòu),會(huì)使用到不同的反射類(lèi)對(duì)象。
reflection: 反射類(lèi). 可以通過(guò)對(duì)象反過(guò)來(lái)獲得對(duì)象的相關(guān)信息.

如果需要知道某個(gè)類(lèi)的結(jié)構(gòu),就應(yīng)該使用refletionClass
存在一個(gè)靜態(tài)方法,refletionClass::export() 可以導(dǎo)出一個(gè)類(lèi)的結(jié)構(gòu)報(bào)告

反射機(jī)制可以獲得目標(biāo)結(jié)構(gòu)的內(nèi)部結(jié)構(gòu)。
并同時(shí)可以驅(qū)動(dòng)目標(biāo)結(jié)構(gòu)運(yùn)行起來(lái).(代理執(zhí)行);

name, "
"; } public function tan($c1, $c2) { echo "
" . $c1 . " ". $c2; } } $p = new Persion(); // $p->say(); // 利用反射對(duì)象調(diào)用方法 $method = new ReflectionMethod("Persion", "say"); // 反射方法對(duì)象 $method->invoke($p); $method2 = new ReflectionMethod("Persion", "tan"); //參數(shù)的反射方法 $method2->invokeArgs($p, array("pink", "red")); ?>
類(lèi)型約束

約束函數(shù),或者方法類(lèi)參數(shù)的類(lèi)型,只能是某個(gè)類(lèi)的對(duì)象。

PHP是弱類(lèi)型,變量可以存儲(chǔ)任意類(lèi)型的數(shù)據(jù)
函數(shù),方法的參數(shù)也是可以接受任意類(lèi)型

但是參數(shù),可以被規(guī)定為,某個(gè)類(lèi)的固定對(duì)象,在參數(shù)前增加類(lèi)名即可。

function sayName ( Student $o ) {
        echo $o->stu_name;        
}

sayName("php");

支持類(lèi)名,和數(shù)組。其它數(shù)據(jù)類(lèi)型不支持。

function sayName ( Array $arr ) {
}
對(duì)象的遍歷

對(duì)象是一個(gè)集合數(shù)據(jù)類(lèi)型

foreach遍歷
遍歷對(duì)象,是依次獲得對(duì)象擁有的屬性的信息(注意,訪問(wèn)修飾符的限制)

class Student {
    
    public $stu_name;
    public $stu_age;
    public $stu_gender;
    
}

$obj = new Student();

$obj->stu_name = "李尋歡";
$obj->stu_age = 30;
$obj->stu_gender = "male";

foreach ( $obj as $val => $key ) {
    
    var_dump($val,$key);
    echo "
"; }

自定義遍歷,iterator
iterator迭代器接口

Iterator接口,PHP預(yù)定義完成。
實(shí)現(xiàn)Iterator接口

// 類(lèi)實(shí)現(xiàn)Iterator 接口
class Team implements Iterator {
    
    public function rewind () {
        reset($this->stu_infos); 
    }
    
    public function valid () {
        return key($this->stu_infos) !== null;
    }
    
    public function current () {
        return current($this->stu_infos);
    }
    
    public function key () {
        
        return key($this->stu_infos);
        
    }
    
    public function next () {
        
        next($this->stu_infos);
        
    }
    
}

魔術(shù)常量
__CLASS__:當(dāng)前類(lèi)名。注意:可以new self 不可以 new __CLASS__
__METHOD__,當(dāng)前方法名。區(qū)別__FUNCTION__

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/21756.html

相關(guān)文章

  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你的“對(duì)象”還好嗎?

    摘要:很多情況下,通常一個(gè)人類(lèi),即創(chuàng)建了一個(gè)具體的對(duì)象。對(duì)象就是數(shù)據(jù),對(duì)象本身不包含方法。類(lèi)是相似對(duì)象的描述,稱(chēng)為類(lèi)的定義,是該類(lèi)對(duì)象的藍(lán)圖或原型。在中,對(duì)象通過(guò)對(duì)類(lèi)的實(shí)體化形成的對(duì)象。一類(lèi)的對(duì)象抽取出來(lái)。注意中,對(duì)象一定是通過(guò)類(lèi)的實(shí)例化來(lái)的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    李昌杰 評(píng)論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你的“對(duì)象”還好嗎?

    摘要:很多情況下,通常一個(gè)人類(lèi),即創(chuàng)建了一個(gè)具體的對(duì)象。對(duì)象就是數(shù)據(jù),對(duì)象本身不包含方法。類(lèi)是相似對(duì)象的描述,稱(chēng)為類(lèi)的定義,是該類(lèi)對(duì)象的藍(lán)圖或原型。在中,對(duì)象通過(guò)對(duì)類(lèi)的實(shí)體化形成的對(duì)象。一類(lèi)的對(duì)象抽取出來(lái)。注意中,對(duì)象一定是通過(guò)類(lèi)的實(shí)例化來(lái)的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    Lyux 評(píng)論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你的“對(duì)象”還好嗎?

    摘要:很多情況下,通常一個(gè)人類(lèi),即創(chuàng)建了一個(gè)具體的對(duì)象。對(duì)象就是數(shù)據(jù),對(duì)象本身不包含方法。類(lèi)是相似對(duì)象的描述,稱(chēng)為類(lèi)的定義,是該類(lèi)對(duì)象的藍(lán)圖或原型。在中,對(duì)象通過(guò)對(duì)類(lèi)的實(shí)體化形成的對(duì)象。一類(lèi)的對(duì)象抽取出來(lái)。注意中,對(duì)象一定是通過(guò)類(lèi)的實(shí)例化來(lái)的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    AaronYuan 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<