什么是編程思想?
所謂的編程思想,就是人們用計算機來解決實際問題的時候的一種思維方式,或者說是一種基本的策略;
常見的編程思想有面向過程和面向?qū)ο?,很多語言的語法各不相同,但是,基本的編程思想?yún)s是差不多的!
PHP同時支持面向?qū)ο蠛兔嫦蜻^程兩種編程思想的語言!
面向過程的編程思想
傳統(tǒng)的面向過程的編程思想總結(jié)起來就八個字——自頂向下,初步細化! 基本策略如下:
ü將要實現(xiàn)的功能描述為一個從開始到結(jié)束的按部就班的連續(xù)的“步驟”(面向過程)
ü依次逐步完成這些步驟,如果某一個步驟的難度比較大,又將該步驟再次細化為若干個子步驟,依次類推,一直到結(jié)束得到想要的結(jié)果!
ü程序的主體是函數(shù),一個函數(shù)就是一個封裝起來的模塊,每個模塊都可以實現(xiàn)特定的功能,各個子步驟往往就是通過各個函數(shù)來完成的,從而實現(xiàn)代碼的重用和模塊化編程!
案例:大家去學?!皥竺蠈W”這件事,可以分成哪些步驟?
所謂的面向過程,就是將上面分析好了的步驟,依次執(zhí)行就行了!
所謂的面向?qū)ο?,就是在編程的時候盡可能的去模擬現(xiàn)實世界!
現(xiàn)實世界中,任何一個操作(動作)或者是任何一個業(yè)務邏輯的實現(xiàn)都需要一個實體去完成,實體就是操作(動作)的支配者,沒有實體,就沒有動作發(fā)生!
思考:上述報名的每一個步驟都有哪些動詞?
提出提供繳分配增加
有動詞就一定有實現(xiàn)這個動詞的實體!
所謂的模擬現(xiàn)實世界,就是使計算機的編程語言與解決相關的業(yè)務邏輯的時候,與真實的現(xiàn)實世界中的業(yè)務邏輯的發(fā)生保持一致!需要使某個動作都是依賴于一個實體的“動作/操作/行動”,可以看做是一個一個的實體在發(fā)揮其各自的“能力”并在內(nèi)部進行協(xié)調(diào)有序的調(diào)用過程!
如果采用面向?qū)ο蟮乃枷?,解決上面的報名的問題應該如下:
1,分析哪些動作是由哪些實體發(fā)出的!
提出提供繳分配增加
學生提出報名->學生繳費->學校收費->老師分配教室->班級增加學生信息
于是,在整個的報名過程中,一共出現(xiàn)了多少個實體?
四個:學生、x學校、老師、班級
在現(xiàn)實中的一個具體的實體,就是計算機編程中的一個具體的對象!
2,定義這些實體,為其增加相應的屬性和功能(功能就是能完成的動作,在面向?qū)ο蟮膶I(yè)術語中叫作方法,其實也就是函數(shù))
1,讓實體,去執(zhí)行相應的功能或動作!
學生提出報名
學生繳費
機構(gòu)收費
教師分配教室
班級增加學生信息
班級管理學生信息
所以說,面向過程主要是針對功能,但是面向?qū)ο笾饕轻槍δ軌驅(qū)崿F(xiàn)這些功能的主體(實體)
從面向過程到面向?qū)ο缶幊趟枷氲霓D(zhuǎn)變
以前寫代碼,首先想到的是需要實現(xiàn)什么功能——可以調(diào)用系統(tǒng)函數(shù),也可以自己定義函數(shù),或者按部就班的執(zhí)行!
以后寫代碼,首先想到的是應該有什么樣的實體(主體)去完成什么樣的功能,再把這些實體的屬性和功能進行封裝,最后才去實現(xiàn)這些實體的功能!
面向?qū)ο蟛皇且环N技術,而是一種思想,是一個解決問題的最根本的思維方式!
所以,面向?qū)ο蟮暮诵乃枷胧牵翰粌H僅是簡單的將某些功能進行封裝,而是對調(diào)用該功能的主體進行封裝,如果一個實體擁有多個功能的話,在使用的過程中,先得到相關的對象,再使用對象去調(diào)用其相關的功能!
面向?qū)ο笈c面向過程的對比
1,都可以實現(xiàn)代碼重用,以實現(xiàn)模塊化編程,但是面向?qū)ο蟮哪K化更深,數(shù)據(jù)更封閉,也更加安全!
2,面向?qū)ο蟮乃季S方式更加貼近現(xiàn)實生活,所以也更容易解決大型的復雜的業(yè)務邏輯!
3,從前期開發(fā)的角度來看,面向?qū)ο蟊让嫦蜻^程要復雜的多,但是從維護和升級的角度來看,面向?qū)ο筮h比面向過程簡單!
面向?qū)ο蟮碾A段概念
OOA:面向?qū)ο蠓治觥OD:面向?qū)ο笤O計、OOP:面向?qū)ο缶幊?/p>
對象的概念,什么叫做對象,object,現(xiàn)實業(yè)務邏輯中的一個動作實體,就對應著OOP編程中的一個對象!
所以:
對象是采用屬性(property)來保存數(shù)據(jù)!
對象是采用方法(method)來管理數(shù)據(jù)!
對象如何產(chǎn)生呢?又如何規(guī)程對象的屬性和方法呢?
在PHP中,對象是由類實例化而來的,也就是說,在PHP中,要想產(chǎn)生一個對象,必須先有一個類!
什么是類?
類其實就是得到對象的一種方法而已!只不過在大多數(shù)的面向?qū)ο缶幊陶Z言中,都是通過類來產(chǎn)生對象,但是,也有的面向?qū)ο蟮恼Z言,產(chǎn)生對象的時候是不需要類的!
為什么要引入類的概念?
其實類本來也是對現(xiàn)實世界的一種模擬,在現(xiàn)實世界中,任何一個實體都有一個類別!
類就是具有相同或相似的特征特性的該類事物的一個通用的名稱!
比如:我們都屬于人類,人類又都屬于靈長動物類,靈長動物類又都屬于動物類,動物類又都屬于生物類!
所以,在php中,一個對象是指現(xiàn)實中的一個具體的實體,而既然現(xiàn)實中的每一個實體都有一個類別,所以OOP中的對象也應該都有一個類!
一個對象的所有應該具有的特性特征信息,都是由其所屬的類決定的!但是每個對象又很有可能有自己不同的特征特性信息,比如我自己這個對象名字叫圣騎士,性別男,會寫程序,會教書;另外一個對象可能叫章子怡,性別女,會演戲!
類的定義
使用class關鍵字來定義的!
這就是一個類,只不過里面什么都沒有!
其中,類名不區(qū)分大小寫,由字母數(shù)字和下劃線構(gòu)成,第一個不能為數(shù)字,一般類名采用大駝峰法命名(主要是區(qū)別方法名或函數(shù)名,我們一般使用小駝峰法來表示函數(shù)名和方法名)
思考:類中可以有什么呢?
先回憶一下以前面向過程中,我們的代碼有什么?
定義常量和變量、定義函數(shù)
使用變量和常量(增刪改查)
調(diào)用函數(shù)、流程控制(if—else for while do-while 、foreach等)
語法上,一個類的內(nèi)部可以具有自己的“變量”和“函數(shù)”,但此時技術術語上應該稱為“屬性”和“方法”,而且,一個類也可以有自己的常量(類常量),
上面的屬性、方法、常量就稱之為是類的“成員”!
所以,定義一個類,其實就是定義三種成員:定義屬性(變量)、定義方法(函數(shù))、定義常量(類常量)
一個需要注意的地方就是,需要對成員進行聲明才可以使用!
聲明采用的是訪問修飾限定符來聲明的,一共有三個:public,protected,private,暫時全部用public來聲明,其中另外兩個后面才學習!
有兩個特殊的:
1,public可以用var來代替!只是對低版本的一種兼容!
2,方法的前面可以省略掉訪問修飾限定符!默認的就是為public
相當于:
上面就定義了一個含有名字和Money金額和一個繳費方法的學生類!
注意,在定義類的時候,如果沒有給某個屬性賦值,默認的就有null型,但是如果給其附上一個初始值,就必須是一個“直接值”,不能是一個表達式計算后的值!
利用類得到對象
注意:類本身什么都做不了,必須利用類得到對象,這個過程就叫作類的實例化!
類的實例化是通過關鍵字new來完成的!
語法是:new類名;
上面已經(jīng)實例化了一個對象,不過對象一般都是放到一個變量里面!
對象如何訪問?使用箭頭-> 實現(xiàn)對對象成員的訪問!
可以實例化多個對象:
對象的編號不同,就說明它們占用不同的內(nèi)存空間!
instanceof運算符
可以利用instanceof運算符來判斷某個對象是否是由某個類實例化而來的!
$this是一個“偽對象”,代表當前所屬的類的當前對象!
$this的自我告白:誰調(diào)用我,我就屬于誰!
思考:屬性和方法都屬于對象的成員,為什么訪問屬性的時候不需要$this關鍵字呢?
再次強調(diào):屬性不能在方法內(nèi)直接訪問!需要找到其對象才能訪問,一個典型的做法就是使用$this->屬性名來訪問當前對象的屬性
通常實例化完一個對象后,都要對對象的屬性進行初始化才有意義
也就是說,每次實例化完一個對象后,都要對該對象進行一次初始化操作!比較麻煩!
思考:如何改善?
可以類中建立一個專門給屬性進行初始化的方法,實例化完之后,直接調(diào)用這個方法,一次完成對象的屬性的初始化!
上面的代碼可以完成對象的屬性的初始化,但是還是不夠方便,每一次new完一個對象后都必須手動調(diào)用init方法才能進行屬性的初始化工作!
如果new的時候,能夠自動調(diào)用init是最好的!
于是,構(gòu)造方式就橫空出世了!
事實上,在實例化一個對象的時候,php會自動的調(diào)用一個名字叫__construct()的方法!
該方法,由于專門負責對新對象進行初始化,稱之為“構(gòu)造方法”!
該方法的最大的特點是,不需要人為的手動調(diào)用,而是由系統(tǒng)在實例化一個對象的時候自動調(diào)用!
問題是,調(diào)用該方法的時候如何將實參傳遞給該方法的形參呢?
需要在實例化對象的時候順便在類名后面增加一對小括號,里面?zhèn)鬟f實參列表
注意:
在php早期版本當中,構(gòu)造方法有一個比較老的語法,就是使用和類名相同的方法作為構(gòu)造方法!
1,如果既有老語法的構(gòu)造方法名,又有新語法的構(gòu)造方法名,系統(tǒng)會主動調(diào)用__construct方法!
2,存在一個最兼容的寫法:
概念:與構(gòu)造方法是一對,構(gòu)造方法是 在一個對象“出世”的時候由系統(tǒng)自動調(diào)用的!而析構(gòu)方法是在一個對象“消失”的時候由系統(tǒng)自動調(diào)用的!
名字是:__destruct()注意:該方法里面不能有參數(shù)!
思考:析構(gòu)方法是在對象消失之前調(diào)用的還是對象消失之后調(diào)用的?
對象消失的幾種情況:當一個腳本周期結(jié)束的時候,明確的使用unset去刪除一個對象的時候,改變對象變量的值,也會自動銷毀!
析構(gòu)方法的作用
注意:析構(gòu)方法主要的作用就是釋放對象所占用的額外的資源,而不是對象本身
我們應該在對象消失的時候,增加析構(gòu)方法,釋放該對象占用的額外的 資源
注意:析構(gòu)方法通常都需要需要額外的定義,只有在對象執(zhí)行的過程中,占用了額外的資源的時候才使用!
總結(jié)一下構(gòu)造方法和析構(gòu)方法的特點:1,都是以__開頭 2,都是由系統(tǒng)自動調(diào)用 3,都是某個特定的情況發(fā)生的時候,調(diào)用相應的方法!
對象的傳值
值傳遞
引用傳遞
所以,對象的值傳遞和引用傳遞其實效果是完全一樣的!
也就是說,對象間的復制,無法開辟一個新的對象空間,有時候,也叫作“淺復制”!
那么,我們?nèi)绾卫靡粋€已有的對象,得到一個新的對象呢?(單獨開辟內(nèi)存空間)
這個時候就需要使用對象的克隆!
對象的克?。核^的克隆,不是通過類的實例化得到新的對象!而是通過一個已有的對象得到一個新的對象!語法如下:新對象 = clone對象
克隆一個對象的時候,會不會觸發(fā)構(gòu)造方法?
回答:不會!因為構(gòu)造方法只有在實例化一個對象的時候才會觸發(fā),但是克隆一個對象不是實例化!
但是,存在一個克隆對象的時候自動調(diào)用的魔術方法!
__clone方法
該方法就是在克隆一個對象的時候,負責對新對象進行相關的初始化!
為什么要有__clone方法?
很有必要,因為客觀世界不存在兩個完全相同的對象!
提醒:以上的案例小伙伴們要去自己敲一遍代碼實現(xiàn)的哦!想要深入學習可以關注小編,每天都會都學習的文章推送給你,我們相互學習,共同成長!