在對象中定義的變量屬性,一般需要public,private,static關(guān)鍵字修飾格仲,如果不加這些關(guān)鍵字修飾的話,需要在變量前加var關(guān)鍵字修飾渡贾。如下:
class Person {
public name; //定義屬性名稱
}
class Person {
var name; //定義屬性名稱
}
構(gòu)造函數(shù)
在php5之前構(gòu)造函數(shù)都是與類名相同的函數(shù)蛉抓,在php5后構(gòu)造函必須是兩個(gè)下劃線開始的函數(shù)庆尘,但是為了向下兼容,在php5中也可以識別與類同名的構(gòu)造函數(shù)巷送。
php5之前:
class Person {
function Perosn(){};
}
php5之后:
class Person {
function __construct(){};
}
析構(gòu)函數(shù)
析構(gòu)函數(shù)是在銷毀一個(gè)對象之前執(zhí)行一些特定的操作驶忌,如關(guān)閉文件等。當(dāng)一個(gè)對象失去引用后就會自動調(diào)用析構(gòu)函數(shù)笑跛。
析構(gòu)函數(shù)是php5才引入的特性付魔。析構(gòu)函數(shù)的定義和構(gòu)造函數(shù)一樣都是以兩個(gè)下劃線開始的固定名稱,析構(gòu)函數(shù)不能帶參數(shù)。如下:
class Person {
function __destruct(){};
}
對象的三大特性:
- 封裝
- 繼承
- 多態(tài)
封裝性
封裝性是通過private關(guān)鍵字在對象里修飾變量或者方法來完成的飞蹂。被private修飾的變量和方法不能再對象外部被直接訪問几苍。如果需要對對象里private變量和方法進(jìn)行操作可以通過定義對象的public方法來訪問。public的變量和方法可以在對象外直接被訪問陈哑。
魔術(shù)方法:__get(), __set(), __isset(), __unset()
如果類中的私有變量太多妻坝,而且還需要訪問多次,我們就需要為每個(gè)私有變量設(shè)置公共接口來訪問芥颈,這樣導(dǎo)致了繁瑣惠勒。php5.1.0以后為我們提供了__set(),__get()等魔術(shù)方法來解決這個(gè)問題爬坑。
當(dāng)我們需要在外部直接訪問私有變量時(shí),如果類的內(nèi)部實(shí)現(xiàn)了對該私有變量的操作涂臣,在外部我們就能直接訪問盾计。如在外部調(diào)用私有變量:
<?php
class Person {
private $name;
private $age;
function __set($propertyname,$propertyvalue){
$this->$propertyname = $propertyvalue;
}
public function say() {
echo "名稱:" .$this->name. ", 年齡" .$this->age;
}
}
$p = new Person();
$p->name = "xzp"; //直接訪問私有變量,系統(tǒng)會自動調(diào)用__set()函數(shù)
$p->age = 8; //直接訪問私有變量
$p->say();
?>
__set()方法:這個(gè)方法用來為私有成員屬性設(shè)置值的赁遗,有兩個(gè)參數(shù)署辉,第一個(gè)參數(shù)為你要為設(shè)置值的屬性名,第二個(gè)參數(shù)是要給屬性設(shè)置的值岩四,沒有返回值哭尝。這個(gè)方法同樣不用我們手工去調(diào)用,它也可以做成私有的剖煌,是在直接設(shè)置私有屬性值的時(shí)候自動調(diào)用的材鹦,同樣屬性私有的已經(jīng)被封裝上 了,如果沒有__set()這個(gè)方法耕姊,是不允許的桶唐,但是如果你在類里面加上了__set($propertyname, $value)這個(gè)方法,在直接給私有屬性賦值的時(shí)候茉兰,就會自動調(diào)用它尤泽,把屬性比如name傳給$propertyname,把要賦的值“zhangsan”傳給$value,通過這個(gè)方法的執(zhí)行,達(dá)到賦值的目的坯约。如果成員屬性不封裝成私有的熊咽,對象本身就不會去自動調(diào)用這個(gè)方法。為了不傳入非法的值闹丐,還可以在這個(gè)方法給做一下判斷横殴。
__get()方法:這個(gè)方法用來獲取私有成員屬性值的,有一個(gè)參數(shù),參數(shù)傳入你要獲取的成員屬性的名稱妇智,返回獲取的屬性值滥玷,這個(gè)方法不用我們手工的去調(diào)用,因?yàn)槲覀円部梢园堰@個(gè)方法做成私有的方法巍棱,是在直接獲取私有屬性的時(shí)候?qū)ο笞詣诱{(diào)用的惑畴。因?yàn)樗接袑傩砸呀?jīng)被封裝上了,是不能直接獲取值的航徙,但是如果你在類里面加上了這個(gè)方法如贷,在使用“echo$p1->name”這樣的語句直接獲取值的時(shí)候就會自動調(diào)用。
__isset() 方法:在看這個(gè)方法之前我們看一下"isset()"函數(shù)的應(yīng)用到踏,isset()是測定變量是否設(shè)定用的函數(shù)杠袱,傳入一個(gè)變量作為參數(shù),如果傳入的變量存在則傳回true窝稿,否則傳回false楣富。
那么如果在一個(gè)對象外面使用"isset()"這個(gè)函數(shù)去測定對象里面的成員是否被設(shè)定可不可以用它呢?分兩種情況伴榔,如果對象里面成員是公有的纹蝴,我們就可以使用這個(gè)函數(shù)來測定成員屬性,如果是私有的成員屬性踪少,這個(gè)函數(shù)就不起作用了塘安,原因就是因?yàn)樗接械谋环庋b了,在外部不可見援奢。那么我們就不可以在對象的外部使用"isset()"函數(shù)來測定私有成員屬性是否被設(shè)定了呢兼犯?
答案是可以的,你只要在類里面加上一個(gè)"__isset()"方法就可以了集漾,當(dāng)在類外部使用"isset()"函數(shù)來測定對象里面的私有成員是否被設(shè)定時(shí)切黔,就會自動調(diào)用類里面的"__isset()"方法了幫我們完成這樣的操作,"__isset()"方法也可以做成私有的帆竹。
__unset()方法:看這個(gè)方法之前呢绕娘,我們也先來看一下"unset()"這個(gè)函數(shù),"unset()"這個(gè)函數(shù)的作用是刪除指定的變量且傳回true栽连,參數(shù)為要刪除的變量险领。那么如果在一個(gè)對象外部去刪除對象內(nèi)部的成員屬性用"unset()"函數(shù)可不可以呢侨舆,也是分兩種情況,如果一個(gè)對象里面的成員屬性是公有的绢陌,就可以使用這個(gè)函數(shù)在對象外面刪除對象的公有屬性挨下,如果對象的成員屬性是私有的,我使用這個(gè)函數(shù)就沒有權(quán)限去刪除脐湾,但同樣如果你在一個(gè)對象里面加上"__unset()"這個(gè)方法臭笆,就可以在對象的外部去刪除對象的私有成員屬性了。
在對象里面加上了"__unset()"這個(gè)方法之后秤掌,在對象外部使用"unset()"函數(shù)刪除對象內(nèi)部的私有成員屬性時(shí)愁铺,自動調(diào)用"__unset()"函數(shù)來幫
我們刪除對象內(nèi)部的私有成員屬性,這個(gè)方法也可以在類的內(nèi)部定義成私有的闻鉴。
繼承性
繼承可以使軟件具有開放性茵乱,可擴(kuò)展性,增加代碼可重用性孟岛。
php的只有單繼承瓶竭,沒有c++的多繼承。
php的繼承使用extends關(guān)鍵字修飾渠羞,語法如下:
<?php
class Student extends Person {}
?>
在繼承中存在訪問類型的控制斤贰,php5支持3中訪問修飾符
- public
- preotected
- private
訪問修飾符的區(qū)別與聯(lián)系:
private | protected | public | |
---|---|---|---|
類本身 | √ | √ | √ |
類的子類中 | √ | √ | |
所有外部成員 | √ |
private
private修飾的成員,對于同一個(gè)類中的成員訪問都沒有限制次询,但是對于該類外的是不允許修改操作的荧恍,該類的子類也不能訪問。
protected
protected修飾的成員屯吊,對于該類的子類及子類的子類都有訪問權(quán)限块饺。但不能被該類的外部代碼訪問。
重載
因?yàn)樽宇惱^承了父類的成員和方法雌芽,子類可以重載父類的方法,當(dāng)子類存在和父類的方法同名時(shí)辨嗽,會把父類的方法覆蓋掉世落,叫方法重載。
<?php
class Person {
function say() {
echo " father";
}
}
class Student extends Person {
function say(){ //重載了父類的say()方法
echo "student";
}
}
?>
php中提供了一種在子類重載的方法中調(diào)用父類被覆蓋的方法糟需。如下:
<?php
class Person {
function say() {
echo " father";
}
}
class Student extends Person {
function say(){ //重載了父類的say()方法
parent::say()屉佳; //調(diào)用父類的方法
echo "student";
}
}
?>
在繼承中常和 final,static洲押,const等關(guān)鍵字一起使用
final
final關(guān)鍵字可以加在類和類中的方法前武花,但不能使用final標(biāo)識成員屬性。
final關(guān)鍵字的作用:
1.使用final標(biāo)識的類不能被繼承杈帐,也就是說被final標(biāo)識的類是最終的版本体箕。
2.在類中被final標(biāo)識的方法不能在子類中被覆蓋
<?php
final class Person{}
?>
static
在類中使用static關(guān)鍵字修飾的成員和成員方法時(shí)屬于整個(gè)類专钉,使用該類new出來的所有對象實(shí)例共享static修飾的成員和成員變量。
因?yàn)閟tatic修飾的變量和方法屬于整個(gè)類累铅,所以可以用類名來訪問跃须。如下:
類型::靜態(tài)屬性成員
類型::靜態(tài)屬性方法()
static修飾的屬性和方法不屬于哪個(gè)對象,是屬于類娃兽,所以不能在類中使用$this關(guān)鍵字菇民,在類中需要使用self關(guān)鍵字來訪問靜態(tài)成員。如下:
self::靜態(tài)屬性成員
self::靜態(tài)屬性方法()
class Person {
static $count;
function getcount(){
return self::$count; //使用$count變量
}
}
靜態(tài)方法使用的注意事項(xiàng)
類中的靜態(tài)方法只能訪問靜態(tài)成員投储,不能訪問非靜態(tài)成員第练。非靜態(tài)方法可以訪問任何成員。
因?yàn)樵L問非靜態(tài)成員需要使用$this 去引用玛荞,但是靜態(tài)方法可以在沒有對象實(shí)例的時(shí)候通過類名調(diào)用娇掏,沒有對象實(shí)例就不存在$this,所以就不能使用非靜態(tài)成員。
利用static在類的特性冲泥,我們可以實(shí)現(xiàn)單例模式驹碍。
單例模式
單例模式簡單來說就是一個(gè)類只能創(chuàng)建一個(gè)對象。
因?yàn)閜hp是腳本語言凡恍,每次訪問都是一次獨(dú)立執(zhí)行的過程志秃,在這個(gè)過程中一個(gè)類有一個(gè)實(shí)例就夠了。比如操作數(shù)據(jù)庫查詢時(shí)只需要實(shí)例化一個(gè)數(shù)據(jù)庫操作類就行了嚼酝,并且只連接一次數(shù)據(jù)庫就可以了浮还,而不是在腳本中為了執(zhí)行多條查詢語句,單獨(dú)的為每條語句實(shí)例化一個(gè)對象闽巩,如果這樣的話效率會非常的低钧舌。所以單例模式的出現(xiàn)為我們很好的解決了這個(gè)問題。
<?php
class DB {
private static $obj = NULL;
private function __construct(){ //構(gòu)造函數(shù)用private修飾涎跨,類不能再外部被實(shí)例化洼冻。
/*在這里完成數(shù)據(jù)庫的連接操作*/
}
static function getInstance() {
if (is_null(self::$obj)){
$obj = new self(); //實(shí)例化本對象
}
return $obj;
}
function query($sql){
echo $sql;
}
}
$db = DB::getInstance(); //獲得唯一的對象
$db->query("select * from user");
?>
const
雖然const和static的功能不同,但是使用的方法非常的相似隅很。在php中定義常量是通過define()函數(shù)來完成的撞牢,但是類中的常量需要使用const關(guān)鍵字來聲明。
在類中用const聲明的常量和static修飾的靜態(tài)變量的訪問方式一樣叔营,都是通過類名來訪問屋彪,或者在成員方法中通過self關(guān)鍵字訪問。類中的const方法只能訪問類中的const常量绒尊。const修飾的常量前面不要$符號畜挥,并且const修飾的常量不可以修改,修改會觸發(fā)錯(cuò)誤婴谱。
<?php
class Myclass {
const CONSTANT = "CONSTANT value";
function showconstant() {
echo self::CONSTANT; //在類中使用常量
}
}
echo Myclass::CONSTANT; //使用類名訪問常量
$cla = new Myclass();
$cla->showconstant();
?>
多態(tài)性
- 抽象類
當(dāng)一個(gè)類中的方法存在一個(gè)抽象方法蟹但,那么這個(gè)類就是抽象類躯泰。
什么是抽象方法?
抽象方法就是沒有方法體的方法矮湘,并且在方法前面用abstract關(guān)鍵字修飾斟冕,如下:
abstract function fun1(); //沒有方法體
如果一個(gè)類中存在抽象方法缅阳,那么這個(gè)類就是抽象類磕蛇,這個(gè)類也必須使用abstract修飾。
在抽象類中可以存在不是抽象的成員和變量十办。抽象類不能實(shí)例化對象秀撇,只能被繼承,繼承抽象類的子類必須全部實(shí)現(xiàn)抽象方法向族,不然子類也是抽象類呵燕。抽象類里的成員和方法不能被private修飾。
abstract class person {
var name;
function getname() {
........
}
abstract function fun1();
}
- 接口
接口也是一種抽象類件相。在接口中只能存在常量和抽象方法再扭。接口的聲明使用interface關(guān)鍵字修飾
interface 接口名稱 {
常量成員 //由const修飾的常量
抽象方法 //在接口的抽象方法不需要abstract修飾
}
接口和抽象類一樣不能實(shí)例化對象,必須由子類繼承,子類必須實(shí)現(xiàn)所有的抽象方法才能實(shí)例化對象夜矗。php中只能繼承一個(gè)類泛范,但是可以繼承多個(gè)接口,而且接口也能繼承接口紊撕。
接口繼承接口使用extends關(guān)鍵字:
interface two extends one {
......
}
類繼承接口使用implements關(guān)鍵字:
class 類名 extends 父類名稱 implements 接口1,接口2,接口3......{
......
}
- 多態(tài)性
多態(tài)是面向?qū)ο蟮娜筇匦灾谐庋b和繼承之外的另一重要特性罢荡。它展現(xiàn)了動態(tài)綁定的功能,也稱為“同名異式”对扶。多態(tài)的功能可讓軟件在開發(fā)和維護(hù)時(shí)区赵,達(dá)到充分的延伸性。事實(shí)上浪南,多態(tài)最直接的定義是讓具有繼承關(guān)系的不同類對象笼才,可以對相同名稱的成員函數(shù)調(diào)用,產(chǎn)生不同反應(yīng)效果络凿。所謂多態(tài)性就是指一段程序能夠處理多種類型對象的能力患整,在PHP中,多態(tài)值指的就是方法的重寫喷众。方法重寫是指一個(gè)子類中可以重新修改父類中的某些方法,使其具有自己的特征紧憾。重寫要求子類的方法和父類的方法名稱相同到千,這可以通過聲明抽象類或是接口來規(guī)范。
我們通過計(jì)算機(jī)USB設(shè)備的應(yīng)用來介紹一下面向?qū)ο笾械亩鄳B(tài)性赴穗,目前USB設(shè)置的種類僅我們自己用過的我想就有十幾種吧憔四。例如USB鼠標(biāo)膀息、USB鍵盤、USB存儲設(shè)備等了赵,這些計(jì)算機(jī)的外部設(shè)備都是通過USB接口連接到計(jì)算機(jī)以后潜支,被計(jì)算機(jī)調(diào)用并啟動運(yùn)行的。也就是計(jì)算機(jī)正常運(yùn)行的同時(shí)柿汛,沒插入一種不同USB設(shè)備冗酿,就為計(jì)算機(jī)擴(kuò)展一樣功能,這正是我們所說的多態(tài)特征络断。那么為什么每個(gè)USB設(shè)備不一樣裁替,但都可以被計(jì)算機(jī)應(yīng)用呢?那是因?yàn)槊總€(gè)USB設(shè)置都要遵守電腦USB接口的開發(fā)規(guī)范貌笨,都具有相同的能被計(jì)算機(jī)加載到并啟用的方法弱判,但運(yùn)行各自相應(yīng)的功能。這也正是我們對多態(tài)的定義锥惋,假設(shè)我們有一個(gè)主程序已經(jīng)開發(fā)完成昌腰,需要后期由其他開發(fā)人員為其擴(kuò)展一些功能,但需要在不改動主程序的基礎(chǔ)上就可以加載到這些擴(kuò)展的功能模塊膀跌,其實(shí)也就是為程序開發(fā)一些插件遭商。這就需要在主程序中需要為擴(kuò)展的插件程序?qū)懞媒涌谝?guī)范,然后每個(gè)插件只有按照規(guī)范去實(shí)現(xiàn)自己的功能淹父,才能被主程序應(yīng)用到株婴。在計(jì)算機(jī)中應(yīng)用USB設(shè)備的程序設(shè)計(jì)如下所示:
?php
//定義一個(gè)USB接口,讓每個(gè)USB設(shè)備都遵守這個(gè)規(guī)范
interface USB{
function run();
}
class Computer{
//計(jì)算機(jī)類中的一個(gè)方法可以應(yīng)用任何一種USB設(shè)備
function useUSB($usb){
$usb->run();
}
}
$computer =new Computer;
$computer ->useUSB(new Ukey()); //為計(jì)算機(jī)插入一個(gè)usb鍵盤設(shè)備暑认,并運(yùn)行
$computer ->useUSB(new Umouse()); //為計(jì)算機(jī)插入一個(gè)usb鼠標(biāo)設(shè)備困介,并運(yùn)行
$computer ->useUSB(new Ustore()); //為計(jì)算機(jī)插入一個(gè)usb存儲設(shè)備,并運(yùn)行
?>
<?php
//擴(kuò)展一個(gè)USB鍵盤設(shè)備蘸际,實(shí)現(xiàn)usb接口
class Ukey implements USB {
function run(){
echo "運(yùn)行USB鍵盤設(shè)備<br>";
}
}
//擴(kuò)展一個(gè)USB鼠標(biāo)設(shè)備座哩,實(shí)現(xiàn)usb接口
class Umouse implements USB {
function run(){
echo "運(yùn)行USB鼠標(biāo)設(shè)備<br>";
}
}
//擴(kuò)展一個(gè)USB存儲設(shè)備,實(shí)現(xiàn)usb接口
class Ustore implements USB {
function run(){
echo "運(yùn)行USB存儲設(shè)備<br>";
}
}
?>
php對象常用函數(shù)
void __autoload(string 粮彤、$class);
//嘗試加載未定義的類classbool class_alias(string $classname, string $alias, [bool $autoload = true]);
//為類classname創(chuàng)建一個(gè)別名alias autoload指定是否調(diào)用__autoload 成功返回true 失敗返回falsebool class_exists(string $classname,[bool $autoload = true])
//檢查類classname是否已定義 autoload指定是否調(diào)用__autoloadbool property_exists(mixed $class, string $proName);
//檢查類或?qū)ο骳lass是否存在proName屬性bool method_exists(mixed $class, string $meName);
//檢查類或?qū)ο骳lass是否存在meName方法bool interface_exists(string $ifname,[bool $autoload = true]);
//檢查接口ifname是否已定義 autoload指定是否調(diào)用__autoloadbool trait_exists(string $trname,[bool $autoload = true]);
//檢查trait是否存在 autoload指定是否調(diào)用__autoloadstring get_class([object $obj]);
//得到對象obj的類名 如果在方法里調(diào)用則參數(shù)可選 如果不是對象返回falsestring get_parent_class([object $obj]);
//得到對象或類的父類名 如果在方法里調(diào)用則參數(shù)可選 如果不是對象且類不存在返回falsearray get_class_vars(string $classname);
在類外調(diào)用只返回公有屬性和靜態(tài)屬性組成的關(guān)聯(lián)數(shù)組根穷;在類內(nèi)調(diào)用返回所有屬性組成的關(guān)聯(lián)數(shù)組。array get_object_vars(object $obj);
在類外調(diào)用只返回公有屬性組成的關(guān)聯(lián)數(shù)組导坟;在類內(nèi)調(diào)用返回除了靜態(tài)變量之外的所有屬性組成的關(guān)聯(lián)數(shù)組屿良。array get_class_methods(mixed $class);
在類外調(diào)用返回公有方法和靜態(tài)方法組成的數(shù)組;類內(nèi)調(diào)用返回所有方法組成的數(shù)組array get_declared_classes(void);
//返回當(dāng)前腳本中已定義類的名字?jǐn)?shù)組array get_declared_interfaces(void);
//返回當(dāng)前腳本中已定義接口的名字?jǐn)?shù)組array get_declared_traits(void);
//返回所有已定義的traits的數(shù)組bool is_subclass_of(mixed $ob,string $class);
//如果對象ob所屬類是類class的子類返回true