類和對象的區別及聯繫:
① 類是抽象的,代表一類事物
② 對象是具體,是類的一個具體實例
③ 類是對象的模板, 對象是類的一個個體實例
【分析對象在內存中存在的形式】
【如果給一個函數傳遞一個對象,實際上是傳遞的一個地址.】
如果給函數傳遞的是基本數據類型( 整數、小數、布爾、字符) ,在默認的情況下是傳遞的值,如果希望傳入地址,要加&:
function test(&$變量....){ }
在php中如果,給一個函數傳遞的是數組,則默認情況下是傳值(拷貝了新的數組),如果希望傳入地址,則應當使用:&$數組名.
函數和成員方法關係:當我們把一個函數寫到某個類中,則該函數可以稱成員方法。舉例如下:
【構造方法——沒有返回值】
$this的使用:
1. $this 本質可以理解就是這個對象的地址
2. 哪個對象使用到$this, 就是哪個對象地址
3. $this不能在類外部使用.
【構造方法的總結】
(1)一旦自定義了一個構造函數,默認的構造函數就被覆蓋了,這時在創建對象的時候就要使用自定義的構造函數.
(2)一個類只能有一個構造函數.(不能重載)
【構造方法的8點說明】
①構造方法名和類名相同(php4版),php5版的構造方法——名可以和類名相同,也可以是__construct()
②構造方法沒有返回值
③主要作用是完成對新對象的初始化,並不是創建對象本身。
④在創建新對象後,系統自動的調用該類的構造方法
⑤一個類有且只有一個構造方法,在php5後雖然__construct() 和類名() 可以共存,但是實際上也只能使用一個。
⑥如果沒有給類自定義構造方法,則該類使用系統默認的構造方法。
⑦如果給類自定義了構造方法,則該類的默認構造方法被覆蓋。
⑧構造方法的默認訪問修飾符是public
【析構方法】——主要用於釋放資源(比如釋放數據庫的鏈接、圖片資源、銷燬某個對象…)
根據上面的代碼可以分析:
析構方法總結:
⑥析構方法不能傳參數
【全局變量】——在程序中都可以使用的變量稱爲全局變量
有一羣小孩在玩堆雪人,不時有新的小孩加入,請問如何知道現在共有多少人在玩?
請使用面向對象的思想,編寫程序解決。
使用全局變量完成(非面向對象)
【靜態變量】
靜態變量與普通變量的區別:
(靜態的變量的基本用法)
1.在類中定義靜態變量:[訪問修飾符] static $變量名;
2. 如何訪問靜態變量
(1)如果在類中訪問,有兩種方法:self::$靜態變量名 , 類名::$靜態變量名
(2)如果在類外訪問,有一種方法:類名::$靜態變量名
【靜態方法】
當我們操作靜態變量的時候,我們可以考慮使用靜態方法,編程中經常需要使用靜態方法去操作靜態變量。
靜態方法的特點:①靜態方法只能操作靜態變量,不能操作非靜態變量。
②普通的成員方法,既可以操作非靜態變量,也可以操作靜態變量。
靜態方法案例:統計所有學生交的學費。
【抽象】
思路延伸:根據不同權限判斷是否可以查看工資:
思路延伸:對指定的值進行修改
注意:成員方法之間互相調用,需要使用$this->…
根據上面的思路延伸,得出如下的魔術方法,不推薦使用,不過要認識。
【繼承extends】
繼承:就是一個子類通過 extends 父類,把父類的 (public/protected)屬性和(public/protected)方法繼承下來.
繼承的基本語法是:
class 類名 extends 父類名{
//在寫自己需要的屬性和方法.
}
繼承的細節討論:
①父類的 public 、protected 的屬性和方法被繼承,private 的屬性和方法沒有被繼承.
②一個類只能繼承一個父類,(直接繼承).如果你希望繼承多個類的屬性和方法,則使用多層繼承
③當創建子類對象的時候,默認情況下,不會自動調用父類的構造方法.
④如果要調用父類的構造方法或者其它方法(public/protected),可以使用類名::方法名() 或parent::方法名()[僅供瞭解]
⑤當一個子類的方法和父類的方法完全一樣(public/protected), 我們稱爲方法的覆蓋(方法重寫).
【方法重載(overload)】
PHP5 中通過魔術方法 __call()來實現方法重載的效果:
關於重載——php5 默認情況下不直接支持方法重載,php5 使用__call魔術方法,模擬一個方法重載的效果.
補充:PHP的魔術常量:
【方法重寫/方法覆蓋(override)】
關於方法重寫的細節討論
1.要實現重寫,要求子類的那個方法的名字和參數列表個數一摸一樣,但是並不要求參數的名稱一樣.
2.如果子類要去調用父類的某個方法(public / protected) 則可以使用 parent::方法名(參數..) , 父類名::方法名(參數...)
3.在實現方法覆蓋的時候,訪問修飾符可以不一樣 //但是必須滿足: 子類的訪問範圍>=父類的訪問範圍
多態的體現:當子類沒有覆蓋父類的方法則調用的是父類的方法,當子類覆蓋了父類的方法,則調用自己的方法。
【抽象類】
①如果一個類使用abstract 來修飾,則該類就是抽象類, 如果一個方法被abstract修飾,則該方法就是抽象方法
②抽象方法不能有方法體abstract public function cry(){ //…}這樣是錯的
③抽象類可以沒有抽象方法.同時還可以有實現了的方法.
abstract public function cry();上面的這行代碼可以沒有。
public function cry(){echo "crying...";}也可以是實現了的方法
④ 如果一個類中,只要有抽象方法,則該類必須聲明爲abstract
abstract class A{ //如果這裏是class A{},則會報錯
abstract function test();
}
⑤如果A1類繼承了一個抽象類A,則要求A1類實現從A類繼承的所有抽象方法
【接口】
【接口的使用基本語法】
interface 接口名{
//屬性
//方法
}
接口的方法都不能有方法體
如何去實現接口?
class 類名 implements 接口名1,接口2.{ //可以繼承多個接口
}
接口它的作用就是:聲明一些方法,供其它類來實現. 接口還體現編程中我們希望的效果高內聚低耦合的特點:
繼承是實現接口的關係一覽圖:
什麼情況下可以考慮使用接口?
(1)定下規範,讓別的程序員來實現。
(2)當多個類,他們之間是平級的關係. 這些類都會去實現某個功能,只是實現的方式不一樣.
【接口的細節】
1. 不能去實例化一個接口
interface iUsb{
}
$a=new iUsb(); (錯誤!!!)
2. 接口中的所有方法,都不能有方法體
3. 一個類可以去實現多個接口,語法:
class 類名 implements 接口1,接口2{
}
4. 接口中可以有屬性,但是必須是常量,並且是public
interface iUsb{
const A=90; //如果是 $a=90; 就會出錯
}
要取到屬性:iUsb::A;
5.接口的方法是public 【默認就是public】 ,不能是 protected 和private,舉例:
interface iUsb{
const A=90;
protected function test(); //會出錯,這裏必須是public
}
6. 一個接口不能繼承其他的類,但是可以繼承別的接口。一個接口可以繼承多個其它的接口.當一個類去實現了某些接口,則必須把所有接口的方法都實現。
類和接口之間關係一覽圖:
代碼說明:
7.一個類可以同時繼承他的父類,而且實現接口:
class A1 extends A implements iUsb2,iUsb3{…}
繼承和實現接口的比較:
(1) 可以認爲實現接口是對單一繼承的補充.
(2) 可以在不破壞類層級關係的前提下,對某個類功能擴展.
【final 關鍵字】
①如果希望某個類不被其它的類來繼承(可能因爲安全考慮...), 可以使用final關鍵字
②如果希望某個方法,比如計算個人所得稅的方法,不能被子類改寫,可以使用fianl 來修飾方法
③ final關鍵字不能去修飾屬性,即 final public $name; 這樣的寫法沒有意義。
【const關鍵字】
當有一個屬性,不希望被修改,則使用const 做成常量(都是public的)。基本用法是:
class 類名{
const 常量名(大寫)= 賦初值;
}
interface 接口名{
const 常量名(大寫)= 賦初值;
}
使用方法 類名::常量名; 接口名::常量
1.常量在定義的時候需要賦初值
2.常量不能修改.
3.常量名不能有 $, 一般是大寫, 默認是public
4.常量在類的內部使用 self::常量的名稱類名::常量的名稱,在類的外部使用類名::常量的名稱.
【代碼】https://github.com/rxbook/study-php-object/tree/master/code03