把大象裝進冰箱里,一共分幾步?
舉個例子
場景:
學生,做,報告。
學生:
姓名,技能
蕭峰,降龍十八掌
令狐沖,獨孤九劍
報告:
某個學生喊出:誰,到!
技能:
某個學生完成某項技能: 誰,技能!
為什么要面向對象
將一系列相關的操作和數據封裝(整理)到一起。因為有些數據和操作要一起出現。
現實中,業務邏輯都是由某個主體發出的。主體可以是人、物、事。編寫程序為的就是解決現實的業務邏輯,因此,采用與現實一致的實現思路,就是主體發出某個操作編程思想,才能更好的描述和解決現實的問題。
基礎概念
class hero{
public $name;
public $jineng;
public function baogao(){
echo $this->name.'喊出了:到!';
}
public function jineng(){
echo $this->name.'釋放了'.$this->jineng.'技能';
}
}
類:
將某種對象的特點,提取出來,形成該種對象的類。依據某個類,將對象創建出來。
對象:
object,現實業務邏輯中的實體,在程序中的映射。主體在現實中叫實體,在程序中叫做對象。
屬性:
property,實體對應的屬性,在程序中,就是對象擁有的屬性,也叫成員屬性。
方法:
method,實體對應的操作,在程序中,稱之為對象的方法,也叫成員方法。
基礎語法
類的創建
通過class聲明,接{}
,在{}
中添加類的屬性和方法。
類的實例化
通過將 類 (class) 實例化 (new) 而產生的叫做對象,類相當于圖紙;實例化相當于施工;對象相當于樓。
使用對象
使用對象的屬性和方法。用運算符->
。對象->方法() 或 對象->屬性
屬性的操作
屬性是數據。針對數據的操作類似對變量的操作。
賦值:取值運算
判斷是否為空:isset(),property_exists()
刪除:unset()
可變屬性:屬性也支持可變標示符語法方法的使用
$this
局部變量
$this就是這個對象的意思
對象間的賦值
使用者的角度:對象之間沒有值傳遞,只有引用傳遞。
如何通過已有的對象,得到一個拷貝(復制)。得到一個一模一樣的新對象
對象的克隆
通過已有的對象,獲取新的對象。與已有對象屬性完全一樣的新對象
語法
新對象 = clone 新對象
內存中會出現一個新的對象空間,克隆時,會將原有對象的所有屬性,一模一樣的復制一份,帶來的問題是,不能通過屬性來區分哪個是已有對象,哪個是克隆對象。
解決辦法
老辦法:在克隆完成時,手動將特定的屬性進行設置。
新辦法(推薦):使用一個特殊的方法來完成。__clone
,其特點是,當進行克隆操作時,會自動使用克隆的新對象來調用該方法。
深克隆
如果某個對象的屬性值為另一個對象,那么克隆該對象時,php是淺克隆,指的是僅僅克隆當前對象,如果屬性還是對象,不完成克隆操作。如果需要深度克隆,需要自己編寫程序。
構造方法
__construct()
在對象實例化的過程中,自動調用。
其作用
實例化對象時,完成對對象的初始化工作,通常設置屬性的初始值,初始方法的調用。該方法可以不存在,但一旦定義,php就會在實例化時調用。
可以用來接收參數。當實例化時,可以在類后使用括號,傳遞實參列表的表達式。可以利用該形參(會被實參賦值),對對象進行初始化工作。
語法上,php支持類名同名的方法為構造方法
析構方法
__destruct()
在對象被銷毀時,自動調用。
什么情況下會導致對象銷毀?
一、腳本周期結束,php會釋放(銷毀)所有的資源,此時會銷毀對象。
二、unset存儲的對象變量。
三、對象變量存儲了其他的值。
其作用
完成收尾的工作
為了保證任何對象的修改,都會存儲到數據庫中,而不會因為對象被銷毀前忘記了調用保存方法,而丟失掉修改的數據,利用析構方法完成任務。釋放額外的資源
關閉數據庫等。
類文件
實際開發過程中,將類的文件獨立出來。程序中如果需要使用到該類,加載即可。require xxx.class.php
,可以更好的重用類,建議的命名方法 類名.class.php
,額外的,類名通常采用首字母大寫的駝峰命名法。
類文件載入
如果項目中類文件很多,怎么辦?
如果項目中類文件很多,就會出現類文件加載吃力,原因有二:
- 重復加載
類只需要加載一次 - 加載多余
加載了不需要的類
可見一種按需加載的機制。需要時,再加載,如果不需要就不加載。這種加載機制稱之為自動加載。
類文件自動加載
需要判斷是否需要類的時機。也即是當程序執行到需要類時(需要&&未定義),同時該類沒有被定義。
$obj = new Obj($params);//php核心程序調用__autoload($params);
function __auto($params){
require './'.$params.'.class.php';
}
此時,php核心會自動調用一個默認為__autoload()
的函數,并將當前需要的類名作為參數傳遞到函數中,我們便可以在方法中根據參數完成相應類的加載即可。
帶來的好處是:如果需要載入多個類,則該方法會被調用多次(只要類沒有定義)。
自動加載業務 邏輯核心
- 類名與類文件地址存在對應關系(自動但是需要按照規律來)
能夠通過 類名 找到類文件的位置才可以!對應關系,php核心是處理不了的,需要人為定義,在定義類名和存儲類文件時,要按照一定的規律(規則)去做。
例如:
核心類 core/ :DbCore.class.php、libCore.class.php
工具類 tool/: iamgeTool.class.php、uploadTool.class.php
//根據類名加載
function __autoload($classname){
if('Core'==substr($classname,-4)){
require './core/'.$classname.'class.php';
}
if('Tool'==substr($classname,-4)){
require './tool/'.$classname.'class.php';
}
//如果存在其他的規則,再加載即可
}
- 實際開發中,常見規律:(效率高,類名隨意但是沒預見性的要提前加映射)
制作類名與類文件的映射列表:
$class_list = array(
'libCore' => './core/libCore.class.php',
'DbCore' => './core/ibCore.class.php',
);
先判斷類是否存在于映射列表中
function __autoload($classname){
if(isset($class_list[$classname]){
require $class_list[$classname];
}
}
綜合起來如下:
function __autoload($classname){
if(isset($class_list[$classname]){
require $class_list[$classname];
}
elseif('Core'==substr($classname,-4)){
require './core/'.$classname.'class.php';
}
elseif('Tool'==substr($classname,-4)){
require './tool/'.$classname.'class.php';
}
//如果存在其他的規則,再加載即可
}
- 但是默認__autoload()為自動加載,有局限:
其一:不能存在多個,項目多個模塊開發,存在不同模塊的自動加載,項目如果使用第三方模塊,也會由第三方定義自動加載(Smarty)。
其二:如果注冊了新的自動加載則默認的自動加載失效。
可見,需要特殊的名字,作為自動加載函數名,告知php核心,自動加載函數名
spl_autoload_register('自定義自動加載函數名');
在使用類之前:注冊一個自動加載函數,通常會在定義函數前就注冊好, 一旦注冊了額外的自動加載函數,則默認的__autoload()就不起作用了,php允許注冊多個額外的自動加載。并且在需要類時,會依據注冊的順序,逐一調用自動加載類。
Have a tyr
一、定義一個類,存在多個屬性,為屬性復制。要求屬性為不同的數據類型(php八種類型),分別嘗試賦值操作。
二、設計一個學生類。要求:
1.存儲學生的姓名,年齡,愛好等屬性。
2.在實例化時完成姓名、性別、的初始化工作,并提示:你好,我是XXX,我來了。
3.提供四個方法,可以設置學生的姓名,性別,年齡,愛好。
4.增加析構方法,要求學生對象被銷毀時,提示再見。
三、定義數據庫操作類,MySqlDB,用于替換之前的mysql函數的基本操作,要求:
1.設計必要的屬性。
2.實例化時對屬性記性初始化。
3.實例化時完成數據庫連接。
4.實例化時設置字符集編碼。
5.實例化時選擇默認的數據庫。
6.增加一個執行sql的方法,可以執行SQL,并返回相應結果。
四、設計足球比賽的管理系統,功能如下,
1.展示信息如下表1
2.點擊球隊實現球隊信息如表2
球隊1 | 比分 | 球隊2 | 比賽時間 |
---|---|---|---|
北京國安 | 2:3 | 廣州恒大 | 2017-10-01 20:30:00 |
球隊|人數| 球員
-|-|-|-
廣州恒大|11|鄭智、郜林、高拉特...