1. 面向?qū)ο蟮幕靖拍?/h2>
1.1 什么是面向?qū)ο缶幊獭?/h3>
準(zhǔn)確的說(shuō)面向?qū)ο缶幊涛覀兘?OOP.面向?qū)ο蟮木幊谭譃槿糠郑好嫦驅(qū)ο蠓治觯∣bject Oriented Analysis,OOA)、面向?qū)ο笤O(shè)計(jì)(Object Oriented Design,OOD),以及面向?qū)ο缶幊蹋∣bject Oriented Programming)罕模。面向?qū)ο缶幊痰膬蓚€(gè)中個(gè)重要的概念是類和對(duì)象。
1.2. 類
世間萬(wàn)物皆對(duì)象鳄袍,萬(wàn)事萬(wàn)物皆對(duì)象芯丧。當(dāng)然,這是在 js 當(dāng)中的一個(gè)概念。在其他的編程語(yǔ)言當(dāng)中援雇,我們說(shuō)世間萬(wàn)物都具有它自身的屬性和方法,通過(guò)這些屬性和方法椎扬,可以將不同的事物區(qū)分開來(lái)惫搏,這就是我們面向?qū)ο箢惖某橄蟆@?人具有身高盗舰。體重和膚色等等這些屬性晶府。還可以吃飯,學(xué)習(xí)走路可以做一些活動(dòng)钻趋。這些活動(dòng)就是人具有的功能川陆。而前面所說(shuō)的體重,膚色蛮位,身高等等這些是什么呢较沪?是屬性。所以我們就可以把人看作是程序當(dāng)中的一個(gè)類失仁。那么人的身高可以看做什么尸曼?可以看做類的屬性走路啊,吃飯呀萄焦,可以看做類的方法控轿。所以什么是類,類是屬性和方法的集合.是面向?qū)ο缶幊套詈诵牡臇|西。也是它的基礎(chǔ)拂封。所以通過(guò)類茬射,我們可以將一些零散的用來(lái)去實(shí)現(xiàn)某一個(gè)功能的代碼進(jìn)行一些管理。比如說(shuō),我們可以創(chuàng)建一個(gè)運(yùn)動(dòng)類冒签。愛(ài)運(yùn)動(dòng)類里面包括有這么些個(gè)屬性姓名身高體重年齡在抛。和性別,然后我再定義幾個(gè)方法萧恕,他能踢足球刚梭,他能打籃球啊肠阱,能舉重能跳高。能吃能玩朴读。
1.3. 對(duì)象
類只是具備某項(xiàng)功能屹徘。一個(gè)抽象模型實(shí)際應(yīng)用當(dāng)中呢,我們需要使用的是對(duì)象磨德。所以我們就需要從那當(dāng)中去實(shí)例化出來(lái)這個(gè)對(duì)象缘回,然后去使用這些對(duì)象。對(duì)象呢典挑,是類進(jìn)行實(shí)例化之后的一個(gè)產(chǎn)物酥宴。它是一個(gè)實(shí)體,是一個(gè)獨(dú)立的個(gè)體。例如您觉,我們?nèi)匀灰匀藶槔?黃種人是人"這句話沒(méi)錯(cuò)拙寡,但是反過(guò)來(lái)說(shuō) "人是黃種人",就有問(wèn)題琳水,因?yàn)槌它S種人肆糕,還有白人,黑人等就在孝,這里的"黃種人"就是"人"這個(gè)類中的一個(gè)實(shí)例對(duì)象诚啃。
1.4. 面向?qū)ο蟮娜筇卣?/h3>
面向?qū)ο缶幊痰拇蟠筇卣骶褪欠庋b性,繼承性私沮,多態(tài)性
1.4.1. 封裝性
封裝性也可稱之為信息隱藏始赎,就是把一個(gè)類的使用和實(shí)現(xiàn)分開,只保留有限的接口(方法)與外部練習(xí)仔燕。同時(shí)也避免程序之間的 相互依賴而產(chǎn)生的不便造垛。
1.4.2. 繼承性
繼承性就是派生類(子類)自動(dòng)繼承一個(gè)或多個(gè)基類(父類)中的屬性與方法。并且我們可以重寫和添加新的屬性方法晰搀∥辶桑可以簡(jiǎn)化對(duì)象和類的創(chuàng)建,提高代碼的可復(fù)用性外恕,繼承分單繼承和多繼承杆逗。PHP 中支持的是單繼承。一個(gè)子類有且只有一個(gè)父類鳞疲。
1.4.3. 多態(tài)性
同一個(gè)類的不同對(duì)象,調(diào)用一個(gè)方法可以獲得不同的結(jié)果罪郊。增強(qiáng)程序的靈活性和重用性。
2. PHP 對(duì)象
2.1. 類的定義
和很多其他面向?qū)ο蟮恼Z(yǔ)言一樣建丧,PHP 通過(guò) class 關(guān)鍵字加類名來(lái)定義類排龄。
<?php
class SportObject{
// ----
}
?>
2.2. 成員方法
類中的函數(shù)被稱為成員方法波势,函數(shù)與成員方法唯一的區(qū)別就是函數(shù)實(shí)現(xiàn)的是某個(gè)獨(dú)立的功能翎朱。而成員方法實(shí)現(xiàn)的是類的一個(gè)行為橄维,它是類的其中一部分。
關(guān)鍵字(修飾符) 成員方法
<?php
class SportObject{
function bealBasketBall($name,$age,$height,$sex){
echo $name.'<br>';
echo $age.'<br>';
echo $height.'<br>';
// return ;
}
}
?>
2.3. 類的實(shí)例化
首先我們要實(shí)例化對(duì)象(通過(guò) new 關(guān)鍵字 實(shí)例化對(duì)象)拴曲,才能通過(guò)對(duì)象執(zhí)行對(duì)應(yīng)的行為方法争舞。通過(guò)對(duì)象->成員方法 來(lái)調(diào)用成員方法。
<?php
class SportObject{
function bealBasketBall($name,$age,$height,$sex){
if($height>=180){
return $name.'符合打籃球的身體素質(zhì)要求澈灼!';
}else{
return $name.'不符合打籃球的身體素質(zhì)要求竞川!';
}
}
}
$s1=new SportObject();
echo $s1->bealBasketBall('張三',20,170,'男');
$s2=new SportObject();
echo $s1->bealBasketBall('李四',40,181,'男');
?>
2.4. 成員變量
類中的變量,也稱為成員變量叁熔。有些人也把它叫做屬性或者字段委乌。成員變量的是用來(lái)保存數(shù)據(jù)信息∪倩兀或者與成員方法進(jìn)行一些交互來(lái)實(shí)現(xiàn)某項(xiàng)功能遭贸。
定義成員變量和成員方法:
關(guān)鍵字(修飾符) 成員變量名
關(guān)鍵字可以使用public ,private, protected, static 中的任意一個(gè)。
訪問(wèn)成員變量和成員方法的方法一樣心软,對(duì)象->成員變量
class SportObject{
// 聲明成員變量壕吹。
public $name;
public $height;
public $sex;
public function boolFootBall($name,$height,$sex){
return $name.'是個(gè)足球運(yùn)動(dòng)員';
}
}
$s1=new SportObject;
$s1->name='佚名';
var_dump($s1);
// $s1->boolFootBall('佚名');
不管是”this->" 還是"對(duì)象名->"哪種格式,后面的變量名是沒(méi)有$符號(hào)的.
2.5. 類常量
常量是在程序運(yùn)行期間,不可改變的量,我們說(shuō)他是一個(gè)恒值,舉例圓周率就是一個(gè)常量。定義常量,我們使用關(guān)鍵字 const删铃。
class SportObject{
const SPORT_TYPE="體育運(yùn)動(dòng)";
public $name;
function setName($name){
$this->name=$name;
}
function getName(){
return $this->name;
}
}
$s1=new SportObject;
$s1->setName('aaa');
echo $s1->getName().'<br>';
echo $s1->name.'<br>';
echo SportObject::SPORT_TYPE.'通過(guò)類::常量名';
2.6 構(gòu)造函數(shù)和析構(gòu)函數(shù)
2.6.1 構(gòu)造函數(shù)
當(dāng)一個(gè)類實(shí)例化為一個(gè)對(duì)象的時(shí)候耳贬,可能可能會(huì)隨著對(duì)象的初始化而初始化一些成員變量。就是給一些成員變量復(fù)制值猎唁。這種情況下我們就可以使用構(gòu)造函數(shù)咒劲。因?yàn)樵蹖?duì)象實(shí)例化過(guò)程當(dāng)中構(gòu)造函數(shù)是自動(dòng)執(zhí)行的。
class Person{
public $name;
public $age;
public $sex;
public $height;
// 我們可以通過(guò)"__construct()"
public function __construct(){
echo '123';
}
}
$p1=new Person;
// 如果成員變量過(guò)多胖秒,寫起來(lái)比較麻煩
// $p1->name='aa';
構(gòu)造函數(shù)是在初始化對(duì)象時(shí)使用的缎患,如果類中沒(méi)有構(gòu)造方法,PHP 會(huì)自動(dòng)生成一個(gè)構(gòu)造函數(shù)阎肝,自動(dòng)生成的構(gòu)造方法是沒(méi)有參數(shù)的挤渔。
2.6.2 析構(gòu)函數(shù)
析構(gòu)函數(shù)的作用和構(gòu)造方法方法剛好相反,是對(duì)象被銷毀時(shí)被調(diào)用的风题,作用是釋放內(nèi)存判导。
<?php
class Person{
public $name;
public $age;
public $sex;
public $height;
// 我們可以通過(guò)"__construct()"
// 構(gòu)造函數(shù)
public function __construct($name,$height,$age,$sex){
// 為成員變量賦值。
$this->name=$name;
$this->height=$height;
$this->age=$age;
$this->sex=$sex;
echo $this->sayHi();
}
public function sayHi(){
return "你好沛硅,我叫$this->name ,我今年$this->age 歲了眼刃,身高$this->height,性別$this->sex";
}
// 析構(gòu)函數(shù)
public function __destruct(){
echo '已經(jīng)被釋放掉了';
}
}
$p2=new Person("佚名",180,23,'女');
2.7 繼承和多態(tài)
其實(shí)繼承和多態(tài)啊最根本的作用就是完成代碼的重用。
2.7.1 繼承
子類繼承父類的所有成員變量方法摇肌,包括構(gòu)造方法擂红,當(dāng)子類被實(shí)例化的時(shí)候,PHP 會(huì)先在子類當(dāng)中找構(gòu)造方法围小,如果子類已經(jīng)有自己的構(gòu)造方法昵骤。PHP 會(huì)先調(diào)用子類的方法树碱。當(dāng)子類當(dāng)中沒(méi)有的時(shí)候,PHP 才會(huì)去調(diào)用变秦。父類當(dāng)中的構(gòu)造方法成榜,這就是繼承。
// 父類(基類)
class SportClass{
// 定義成員變量
public $name;//姓名
public $age;//年齡
public $weight;//體重
public $sex;//性別
public function __construct($name,$age,$weight,$sex){
$this->name=$name;
$this->age=$age;
$this->weight=$weight;
$this->sex=$sex;
}
function sayHi(){
echo '你好蹦玫,我是'.$this->name;
}
}
/**子類(派生類)BealBasketBall*/
class BealBasketBall extends SportClass{//定義子類赎婚,繼承父類
// 定義成員變量 身高
public $height;
public function __construct($name,$height){
$this->height=$height;
$this->name=$name;
}
// function sayHi(){
// echo '你好,我是'.$this->name;
// }
}
$b1=new BealBasketBall('曾輝',198);
2.7.2 多態(tài)
多態(tài)好比有一個(gè)成員類樱溉,方法是讓大家去游泳挣输,這時(shí)有人帶著游泳圈還有人拿著浮板。還有人什么也不帶福贞。雖然是同一種方法,但是卻產(chǎn)生了不同的形態(tài),這就叫多態(tài)歧焦。
多態(tài)存在兩種形式,覆蓋和重載肚医。
1).所謂的覆蓋绢馍,在子類中重寫父類的方法。而在子類的對(duì)象當(dāng)中肠套,雖然調(diào)用的是父類當(dāng)中相同的方法舰涌,但返回的結(jié)果是不一樣的。上面的那個(gè)例子當(dāng)中都調(diào)用了父類當(dāng)中的說(shuō)明方法你稚。但是返回的結(jié)果卻不同瓷耙。
2).再就是重載,重載是類的多態(tài)的另外一種體現(xiàn)。函數(shù)在重載的時(shí)候會(huì)有一個(gè)標(biāo)識(shí)符刁赖。被當(dāng)做多個(gè)函數(shù)名稱搁痛。而且呢,能夠通過(guò)函數(shù)的參數(shù)的個(gè)數(shù)或者參數(shù)的類型宇弛,將這些同名的函數(shù)區(qū)分開來(lái)鸡典,(方法名稱是相同的),可能是參數(shù)的數(shù)量或者參數(shù)的類型不同枪芒。以便于去使用和調(diào)用的時(shí)候不發(fā)生混淆彻况。
PHP所提供的重載(overloading)是指動(dòng)態(tài)地創(chuàng)建類屬性和方法。我們是通過(guò)魔術(shù)方法(magic methods)來(lái)實(shí)現(xiàn)的舅踪。
class A{
function __call($name,$num){
echo "方法名稱:".$name.'<br>';
echo '參數(shù)存在的個(gè)數(shù):'.count($num).'<br>';
if(count($num)==1){
echo $this->list1();
}
if(count($num)==2){
echo $this->list2();
}
}
public function list1($a){
return "這是list1函數(shù)纽甘,:參數(shù):$a";
}
public function list2($a,$b){
return "這是list1函數(shù),:參數(shù)1:$a ,參數(shù)2:$b ";
}
}
$a=new A;
$a->list(1);
2.8 "$this->" 和"::"的使用
PHP通過(guò)為變量this->和域的操作符"::"來(lái)訪問(wèn)自己的成員變量和成員方法的
1.this->
在本類內(nèi)部我們可以通過(guò)this訪問(wèn)當(dāng)前實(shí)例化對(duì)象抽碌,調(diào)用方法或成員變量的話則使用 "this->成員變量" || "this->成員方法" 來(lái)訪問(wèn)悍赢。所以 this-> 只在類的內(nèi)部使用
class Demo{
function exam(){
if(isset($this)){
echo '$this的值:'.get_class($this);
}else{
echo '$this 未定義';
}
}
}
$d1=new Demo;
$d1->exam();
2. 操作符::
$this只能在類的內(nèi)部去使用。操作符"::"可以在沒(méi)有聲明任何實(shí)例的情況下,訪問(wèn)類當(dāng)中的成員方法或成員變量左权。
關(guān)鍵字::變量名/常量名/方法名
關(guān)鍵字有三種情況:
- parent: 可以調(diào)用父類中的 成員變量瞒斩,成員方法和常量
- self:可以調(diào)用當(dāng)前類中的 靜態(tài)成員和常量
- 類名:可以調(diào)用本類中的靜態(tài)變量,常量和靜態(tài)方法
class A{
const NAME_='A';
public $name;
public $age;
public $sex;
public function __construct($name,$age,$sex){
$this->name=$name;
$this->age=$age;
$this->sex=$sex;
}
}
class B extends A{
const NAME_='B';
public $height;
public $weight;
public function __construct($name,$age,$sex,$height,$weight){
parent::__construct($name,$age,$sex);
$this->height=$height;
$this->weight=$weight;
}
public function a(){
self::NAME_;
parent::NAME_;
}
}
$b1=new B('姓名','年齡','xingbie','身高','體重');
B::NAME_;
2.9 修飾符
public涮总、private、protected祷舀、static和final瀑梗。這些關(guān)鍵字是用來(lái)限定類成員(包括方法和變量)的訪問(wèn)權(quán)限。
2.9.1 public(公共成員)
顧名思義就是可以公開的裳扯,沒(méi)有必要去隱藏的一些數(shù)據(jù)信息抛丽。可以用public來(lái)去修飾當(dāng)前的成員方法或者成員變量饰豺。它可以在程序的任何位置出現(xiàn)(類的內(nèi)部亿鲜,類的外部)≡┒郑可以被其他的類和對(duì)象去調(diào)用蒿柳。子類呢可以繼承和使用父類當(dāng)中所有的,公共成員漩蟆。
class Person{
public $name="李雷";
public function fn(){
// 1.可以在類的內(nèi)部訪問(wèn)垒探,對(duì)當(dāng)前類的 內(nèi)部可見
echo $this->name;
}
}
class Students extends Person{
public function fn1(){
// 2.可以在子類的內(nèi)部訪問(wèn),對(duì)子類的內(nèi)部可見
echo $this->name;
$this->fn();
}
}
// 3.在類的外部可見
$s1=new Person();
$s1->fn();
$s2=new Students();
$s2->fn();
$s2->fn1();
2.9.2 private(私有成員)
被private關(guān)鍵字所修飾的成員方法和變量怠李,只能在所屬類的內(nèi)部被調(diào)用和修改圾叼,不可以在類外部訪問(wèn),在子類中也不可以捺癞。
<?php
class Book{
private $name='HTML';
public function setName($name){
// 1.在當(dāng)前類內(nèi)部 可訪問(wèn)
$this->name=$name;
}
public function getName(){
echo $this->name;
}
private function c1(){
echo '123';
}
}
class Histoty extends Book{
public function getBookName(){
// 2.在子類內(nèi)部不可見 不可訪問(wèn)繼承來(lái)的父類中的私有成員變量 私有方法
echo $this->name;
$this->c1();
}
}
// $b1=new Book;
// $b1->setName('PHP');
// $b1->getName();
// 3.在類的外部不可訪問(wèn) 私有成員變量或私有成員方法
// $b1->name='js';
// $b1->c1();
$h1=new Histoty();
$h1->getBookName();
對(duì)于成員方法和成員變量夷蚊,如果沒(méi)有指定關(guān)鍵字,那就默認(rèn)是public髓介。
2.9.3 protected(保護(hù)成員)
被protected 修飾的類成員,可以在當(dāng)前類和子類中被調(diào)用惕鼓。去其他地方則不可以訪問(wèn)。
class Person{
protected $money=10;
public function fn(){
echo $this->money;
// 1.在當(dāng)前的內(nèi)部可以訪問(wèn)
}
}
class Stu extends Person{
public function fn1(){
echo $this->money;
// 2\. 可以在子類的內(nèi)部訪問(wèn)
}
}
// 3\. 在類的外部不能直接訪問(wèn)唐础,
$p1=new Person;
$p1->fn();
// echo $p1->money;
$s1=new Stu;
$s1->fn1();
2.10 靜態(tài)成員(變量呜笑,方法)
不是所有的方法都要通過(guò)創(chuàng)建對(duì)象來(lái)去調(diào)用的,我們可以彻犁。通過(guò)給變量或者方法加上static關(guān)鍵字來(lái)直接調(diào)用叫胁。也叫做訪問(wèn)靜態(tài)成員。
//關(guān)鍵字::靜態(tài)成員
關(guān)鍵字可以有兩種:
- self汞幢,在類的內(nèi)部調(diào)用靜態(tài)成員是使用驼鹅。
- 靜態(tài)成員所在的類名,在類的外部調(diào)用類內(nèi)部的靜態(tài)成員時(shí)所使用。
在靜態(tài)方法當(dāng)中只能調(diào)用靜態(tài)變量输钩,而不能調(diào)用普通的變量豺型。而普通方法里面可以調(diào)用靜態(tài)變量。
使用靜態(tài)成員买乃,除了可以不需要實(shí)例化對(duì)象外姻氨,另一個(gè)作用就是在對(duì)象被銷毀后,仍然保留被修改的靜態(tài)數(shù)據(jù)剪验,以便于下次繼續(xù)使用肴焊。
class Book{
static $num=0;//聲明一個(gè)靜態(tài)變量$num,初始值為0;
public function showMe(){
echo '您是第'.self::$num.'位訪客';
self::$num++;//
}
}
$b1=new Book();
$b1->showMe();
$b2=new Book();
$b2->showMe();
echo '一共有'.Book::$num.'位訪客';
2.11 final 關(guān)鍵字
被final修飾過(guò)的類和方法就是"最終的版本"功戚,如果類被final修飾過(guò)娶眷,該類不可以再被繼承,也不能再有子類啸臀。
final class Book{
public $name='';
public function __construct($name){
$this->name=$name;
}
}
class Histoty extends Book{
public $height='';
}
//結(jié)果: Fatal error: Class Histoty may not inherit from final class (Book)
如果方法被final修飾過(guò)届宠,方法在子類中不可以進(jìn)行重寫,也不可能被覆蓋乘粒。
class Book{
public $name='';
public function __construct($name){
$this->name=$name;
}
final public function getName(){
echo $this->name;
}
}
class Histoty extends Book{
public $height='';
public function getName(){
echo '123';
}
}
//結(jié)果:Fatal error: Cannot override final method Book::getName() in
2.12 對(duì)象類型檢測(cè)
instanceof操作符可以檢測(cè)當(dāng)前對(duì)象是屬于哪一個(gè)類豌注。
ObjectName instanceof ClassName
class Book{
public $name='';
public function __construct($name='佚名'){
$this->name=$name;
}
}
class History{
}
$a=new Book;
$b=new History;
// var_dump($a instanceof Book);//true
var_dump($b instanceof Book);//false
3.魔術(shù)方法(__)
3.1 __get和__set() 方法
這兩個(gè)魔術(shù)方法的作用分別是:
當(dāng)程序試圖去寫入一個(gè)不存在或者不可見的成員變量的時(shí)候PHP就會(huì)執(zhí)行__set()方法。__set()方法呢灯萍,包括有兩個(gè)參數(shù),分別是變量名稱和變量的值幌羞,這兩個(gè)參數(shù)不可省略。
當(dāng)程序調(diào)用一個(gè)未定義或者不可見的成員變量的時(shí)候竟稳,可以通過(guò)__get()方法來(lái)去讀取變量的值.__get()這個(gè)方法有一個(gè)參數(shù)表示你要調(diào)用的這個(gè)變量名稱属桦。
<?php
class SportClass{
public $height='1231';
private $type='21312';
public function __get($name){
if(isset($this->$name)){//判斷變量是否被聲明
echo '變量'.$name.'值:'.$this->$name.'<br>';
}else{
echo '變量'.$name.'未定義';
$this->$name=0;
echo $this->$name;
}
}
public function __set($name,$value){
if(isset($this->$name)){
echo '私有成員';
echo '變量'.$name.'賦值:'.$value.'<br>';
}else{
$this->$name=$value;
echo '變量不存在';
}
}
}
$b=new SportClass();
// echo $b->type;
// echo $b->sex;
// $b->type='213';
$b->sex=234;
echo $b->sex;
3.2 __tostring()方法
當(dāng)使用echo或print輸出對(duì)象時(shí),將對(duì)象轉(zhuǎn)化為字符串他爸。
class SportClass{
private $type='21312';
public function __tostring(){
return $this->type;
}
}
$b=new SportClass;
echo $b;
3.3 __autoload()方法
嘗試加載未定義的類是聂宾,觸發(fā)__autoload()方法,__autoload()接受一個(gè)參數(shù)诊笤,參數(shù)是類的名稱系谐。
function __autoload($classname){
$class_path=lcfirst($classname).'Class.php';
if(file_exists($class_path)){
include_once($class_path);
}
}
$b=new BaseFile;
var_dump($b);
$c=new Base();
var_dump($c);
3.4 中文字符串截取類
在PHP當(dāng)中我們經(jīng)常要去對(duì)字符串進(jìn)行一些截取。如果是英文字符串的話讨跟,我們可以直接使用substr()函數(shù)來(lái)去完成纪他。但是當(dāng)出現(xiàn)中文字符串的時(shí)候,如果你依然使用這個(gè)substr()函數(shù)晾匠,就有可能會(huì)出現(xiàn)亂碼的情況茶袒。因?yàn)橐粋€(gè)漢字是由兩個(gè)字節(jié)組成的。所以當(dāng)截取的字符如果出現(xiàn)奇數(shù)的時(shí)候凉馆,就有可能將一個(gè)漢字給拆分開來(lái)薪寓。從而導(dǎo)致輸出一個(gè)不完整的漢字,顯示出來(lái)就是亂碼亡资。