今天來和大家介紹PHP的物件導向。說到物件導向,我必須提一下面向過程,因為本人在初學時,常常分不清楚物件導向和物件導向過程,
物件導向程式設計(OOP)是我們程式設計的基本技能, PHP5對OOP提供了良好的支援。如何運用OOP的想法來進行PHP的高階編程,對於提升PHP編程能力和規劃好Web開發架構都是非常有意義的。下面我們就透過實例來說明使用PHP的OOP進行程式設計的實際意義和應用方法。
我們通常在做一個有資料庫後台的網站的時候,都會考慮到程式需要適用於不同的應用程式環境。和其他程式語言有所不同的是,在PHP中,操作資料庫的是一系列的具體功能函數(如果你不使用ODBC介面的話)。這樣做雖然效率很高,但封裝卻不夠。如果有一個統一的資料庫接口,那麼我們就可以不對程式做任何修改而適用於多種資料庫,從而使程式的移植性和跨平台能力都大大提高。
以下就來跟大家介紹它們的差異:
#物件導向專注於由哪個物件來處理一個問題。
其最大特點是由一個一個具有屬性和功能的類,從類別中拿到對象,進而處理問題。
以過程專注於解決一個問題的流程。其最大特點是由一個一個的函數去解決處理這個問題的一系列過程。
1、什麼是類?
具有相同屬性(特徵)和方法(行為)的一系列個體的集合,類別是抽象的概念。
2、什麼是物件?
從類別中,得到的具有具體屬性值的個體,稱為物件。對像是一個具體的個體。
eg:人類;張三
3、類別和物件的關係?
類別是物件的抽象化!對像是類別的具體化!
類別只是表示這類物件有哪些屬性,但是不能有具體的值,所以類別是抽象的。
物件是將類別的所有屬性賦值後,產生具體的個體,所有物件是具體的。
##1、如何宣告一個類別:
class 類別名稱{
存取修飾符 $屬性[=預設值];
[存取修飾符] function 方法(){}
}
2、宣告一個類別的注意事項:
①類別名稱只能有字母數字底線組成,開頭不能是數字,必須符合大駝峰法則;
②類別名稱必須使用class修飾,類別名稱後面一定不能有();
③屬性必須要帶存取修飾符,方法可以不帶存取修飾符。
3、實例化物件及物件屬性方法的呼叫:
$物件名稱 = new 類別名稱(); //()可以不帶
類別外部呼叫屬性與方法:
$物件名稱-> $屬性名稱; //使用->呼叫屬性時,屬性名稱不能帶$符號
類別內部呼叫屬性與方法:
$this -> $屬性名;
#1、什麼是建構子?
建構子是類別中的一個特殊函數,當我們使用new關鍵字實例化物件時,相當於呼叫了類別的建構子。
2、建構子有什麼作用?
實例化物件時,自動調用,用於給物件的屬性賦初值!
3、建構子的寫法:
①建構函式名,必須與類別同名
[public] function Person($name){
$this -> name = $name;
#}
②使用魔術方法__construct
[public] function __construct($name){
# $this -> name = $name;
##}
4、建構子注意事項:
①第一種寫法,建構函式名稱必須與類別同名! ! ! !
②如果一個類別沒有手寫建構函數,則系統預設會有一個空參構造,因此可以使用new Person();
如果我們寫了帶參數的建構函數,則不會再有空參構造,也就是不能直接使用new Person();
Person後面的()中的參數列表,必須符合建構子的要求! ! ! !
③如果兩種建構子同時存在,將使用__construct。
5、析構函數:__destruct():
#①析構函數在物件被銷毀釋放之前自動呼叫;
②析構函數不能帶有任何的參數;
③析構函數常用於物件使用完以後,釋放資源,關閉資源等。
6、魔術方法:
PHP中,給我們一系列用__開頭的函數,這些函數不需要自己手動調用,
會在適當的時機自動調用,這類函數稱為魔術稱為魔術函數。
eg:function __construct(){} 在類別new一個物件時自動呼叫
function __destruct(){} 在物件被銷毀時自動呼叫
我們要求,除了魔術方法之外,自訂的函數與方法不能使用__開頭。
最後,一般對於功能比較複雜的類,我們會單獨的寫到一個類別文件中。
類別檔案的命名,同一小寫,使用"類別名稱小寫.class.php"的方式命名。
在其他檔案中使用這個類別時,可以使用include導入這個".class.php"檔案。
#
二、封裝與繼承 |
1、什麼是封裝?
透過存取修飾符,將類別中不需要外部存取的屬性和方法進行私有化處理,以實現存取控制。
*注意:是實現存取控制,而不是拒絕存取。也就是說,我們私有化屬性後,需要提供對應的方法,讓使用者透過我們提供的方法處理屬性。
2、封裝的作用?
①使用者只關心類別能夠提供的功能,不關心功能實現的細節! (封裝方法)
②對使用者的資料進行控制,防止設定不合法數據,控制傳回給使用者的資料(屬性封裝+set/get方法)
3、實作封裝作業?
①方法的封裝
對於一些只在類別內部使用的方法,而不是像對外部提供使用,那麼,這樣的方法我們可以使用private進行私有化處理。
1 private function formatName(){} //这个方法仅仅能在类内部使用$this调用2 function showName(){3 $this -> formatName();4 }
②屬性的封裝+set/get方法
為了控制屬性的設定以及讀取,可以將屬性進行私有化處理,並要求使用者透過我們提供的set/get方法進行設定
1 private $age;2 //set方法3 function setAge($age){4 $this->age=$age;5 }6 //get方法7 function getAge(){8 return $this->age;9 }
$物件->getAge();
$物件->setAge(12);
③屬性的封裝+魔術方法
__get( -> __set(, ->= }
#$物件->age; //存取物件私有屬性時,自動呼叫__get()魔術方法,並且將存取的屬性名稱傳給__get()方法;
$物件->age=12; //設定物件私有屬性時,自動呼叫__set()魔術方法,並且將設定的屬性名稱以及屬性值傳給__set()方法;
注意:在魔術方法中,可以使用分支結構,判斷$key的不同,進行不同操作。
4、關於封裝的魔術方法:
①__set($key,$value):給類別私有屬性賦值時自動調用,調用時給方法傳遞兩個參數:需要設定的屬性名,屬性值。
②__get($key,$value):讀取類別私有屬性時自動調用,呼叫時給方法傳遞一個參數,需要讀取的屬性名稱;
③__isset($key):外部使用isset()函數偵測私有屬性時,自動呼叫。
>>>類別外部使用isset();偵測私有屬性,預設是偵測不到的。 false
>>>所以,我們可以使用__isset();函數,在自動呼叫時,回傳內部偵測結果。
1 function __isset($key){2 return isset($this -> $key);3 }
当外部使用isset($对象名->私有属性);检测时,将自动调用上述__isset()返回的结果!
④__unset($key):外部使用unset()函数删除私有属性时,自动调用;
1 function __unset($key){ 2 unset($this -> $key); 3 }
当外部使用unset($对象名->私有属性);删除属性时,自动将属性名传给__unset(),并交由这个魔术方法处理。
1、如何实现继承?
给子类使用extends关键字,让子类继承父类;
class Student extends Person{}
2、实现继承的注意事项?
①子类只能继承父类的非私有属性。
②子类继承父类后,相当于将父类的属性和方法copy到子类,可以直接使用$this调用。
③PHP只能单继承,不支持一个类继承多个类。但是一个类进行多层继承。
class Person{}
class Adult extends Person{}
class Student extends Adult{}
//Student 类就同时具有了Adult类和Person类的属性和方法
3、方法覆盖(方法重写)
条件一: 子类继承父类
条件二:子类重写父类已有方法
符合上述两个条件,称为方法覆盖。覆盖之后,子类调用方法,将调用子类自己的方法。
同样,除了方法覆盖,子类也可以具有与父类同名的属性,进行属性覆盖。
如果,子类重写了父类方法,如何在子类中调用父类同名方法?
partent::方法名();
所以,当子类继承父类时,需在子类的构造中的第一步,首先调用父类构造进行复制。
1 function __construct($name,$sex,$school){2 partent::__construct($name,$sex);3 $this -> school = $school;4 }
三、PHP关键字 |
1、final
①final修饰类,此类为最终类,不能被继承!
②final修饰方法,此方法为最终方法,不能被重写!
③final不能修饰属性。
2、static
①可以修饰属性和方法,分别称为静态属性和静态方法,也叫类属性,类方法;
②静态属性,静态方法,只能使用类名直接调用。
使用"类名::$静态属性" , "类名::静态方法()"
Person::$sex; Person::say();
③静态属性和方法,在类装载时就会声明,先于对象产生。
④静态方法中,不能调用非静态属性或方法;
非静态方法,可以调用静态属性和方法。
(因为静态属性和方法在类装载时已经产生,而非静态的属性方法,此时还没有实例化诞生)
⑤在类中,可以使用self关键字,代指本类名。
1 class Person{2 static $sex = "nan";3 function say(){4 echo self::$sex;5 }6 }
⑥静态属性是共享的,也就是new出很多对象,也是共用一个属性。
3、const关键字:
在类中声明常量,不能是define()函数!必须使用const关键字。
与define()声明相似,const关键字声明常量不能带$,必须全部大写!
常量一旦声明,不能改变。调用时与static一样,使用类名调用Person::常量。
4、instanceof操作符:
检测一个对象,是否是某一个类的实例。(包括爹辈,爷爷辈,太爷爷辈……)
$zhangsan instanceof Person;
① . 只能连接字符串; "".""
② => 声明数组时,关联键与值["key"=>"value"]
③ -> 对象($this new出的对象)调用成员属性,成员方法;
④ :: ①使用parent关键字,调用父类中的同名方法:parent::say();
②使用类名(和self)调用类中的静态属性,静态方法,以及常量。
四、单例 |
單例模式也稱為單態模式。可以保證,一個類別只能有一個物件實例。
實作重點:
①建構函式私有化,不允許使用new關鍵字建立物件。
②對外提供取得物件的方法,在方法中判斷物件是否為空。
若為空,則建立物件並傳回;如果不為空則直接傳回。
③實例物件的屬性以及取得物件的方法必須都是靜態的。
④之後,建立物件只能使用我們提供的靜態方法。
eg:$s1 = Singleton::getSingle();
#
五、物件串列化和魔術方法 |
***关键词:clone与__clone、__antoload()、串行化与反串行化(序列化与反序列化)、类型约束、魔术方法小总结(12个)
1、当使用=讲一个对象,赋值给另一个对象时,赋的实际是对象的地址。
两个对象指向同一地址,所以一个对象改变,另一个也会变化。
eg: $lisi = $zhangsan;
2、如果想要将一个对象完全克隆出另一个对象,两个对象是独立的,互不干扰的,
则需要使用clone关键字;
eg: $lisi = clone $zhangsan; //两个对象互不干扰
3、__clone():
①当使用clone关键字,克隆对象时,自动调用clone函数。
②__clone()函数,类似于克隆时使用的构造函数,可以给新克隆对象赋初值。
③__clone()函数里面的$this指的是新克隆的对象
某些版本中,可以用$that代指被克隆对象,绝大多数版本不支持。
4、__toString()
当使用echo等输出语句,直接打印对象时调用echo $zhangsan;
那么,可以指定__toString()函数返回的字符串;
1 function __toString(){2 return "haha";3 }4 echo $zhangsan; //结果为:haha
5、__call()
调用类中未定义或未公开的方法时,会自动执行__call()方法。
自动执行时,会给__call()方法传递两个参数;
参数一:调用的方法名
参数二:(数组)调用方法的参数列表。
①这是唯一一个不在类中使用的魔术方法;
②当实例化一个不存在的类时,自动调用这个魔术方法;
③调用时,会自动给__autoload()传递一个参数:实例化的类名
所以可以使用这个方法实现自动加载文件的功能。
1 function __autoload($className){2 include "class/".strtolower($className).".class.php";3 }4 $zhangsan=new Person();//本文件内没有Person类,会自动执行__autoload()加载person.class.php文件
1、串行化:将对象通过一系列操作,转化为一个字符串的过程,称为串行化。
(对象通过写出描述自己状态的数值来记录自己)
2、反串行化:将串行化后的字符串,再转为对象的过程,称为反串行化;
3、什么时候使用串行化?
①对象需要在网络中传输的时候
② 对象需要在文件或数据库中持久保存的时候
4、怎样实现串行化与反串行化
串行化: $str=serialize($zhangsan);
反串行化:$duixiang=unserialize($str);
5、__sleep()魔术方法:
①当执行对象串行化的时候,会自动执行__sleep()函数;
②__sleep()函数要求返回一个数组,数组中的值,就是可以串行化的属性;不在数组中的属性,不能被串行化;
function __sleep(){
return array("name","age"); //只有name/age两个属性可以串行化。
}
6、__wakeup()魔术方法
①当反串行化对象时,自动调用__wakeup()方法;
②自动调用时,用于给反串行化产生的新对象属性,进行重新赋值。
1 function __wakeup(){ 2 $this -> name = "李四"; 3 }
1、类型约束:是指在变量时,加上数据类型,用于约束此变量只能存放对应的数据类型。
(这种操作常见于强类型语言,在PHP中,只能实现数组和对象的类型约束)
2、如果类型约束为某一个类,则本类以及本类的子类对象,都可以通过。
3、在PHP中,类型约束,只能发生在函数的形参中。
1 class Person{}2 class Student extends Person{}3 function func(Person $p){ //约束函数的形参,只接受Person类及Person子类4 echo "1111";5 echo $p -> name;6 }
func(new Person()); √
#func(new Student()); √
func("111"); ×
#形如new Person();的形式,我們稱之為"匿名物件";
※※※基底類別:父類別
※※※衍生類別:子類別
#五
魔術方法小總結
#1、__construct():建構函數,new一個物件時,自動調用。
4、__set():給類別的私有屬性賦值時,自動呼叫。傳遞需要設定的屬性名稱和屬性值;5、__isset():使用isset()偵測物件私有屬性時,自動呼叫。傳遞偵測的屬性名,傳回isset($this -> 屬性名);#6、__unset():使用unset()刪除物件私有屬性時,自動呼叫。傳遞刪除的屬性名,方法中執行unset($this -> 屬性名); |
1、什麼是抽象方法?
沒有方法體{}的方法,必須使用abstract關鍵字修飾。這樣的方法,我們稱為抽象方法。
abstract function say(); //抽象方法
#2、什麼是抽象類別?
使用abstract關鍵字修飾的類別就是抽象類別。
abstract class Person{}
3、抽象類別的注意事項:
① 抽象類別可以包含非抽象方法;
② 包含抽象方法的類別必須是抽象類,抽象類別不一定必須包含抽象方法;
③ 抽象類,不能實例化。 (抽象類別中可能包含抽象方法,抽象方法沒有方法體,實例化呼叫沒有意義)
我們使用抽象類別的目的,就是限制實例化! ! !
4、子類別繼承抽象類,那麼子類別必須重寫父類別的所有抽象方法,除非,子類別也是抽象類別。
5、使用抽象類別的作用?
① 限制實例化。 (抽象類別是不完整的類,裡面的抽象方法沒有方法體,所以不能實例化)
② 抽象類別為子類別的繼承提供一個規範,子類別繼承一個抽象類,則必須包含並且實作抽象類別中已定的抽象方法。
#七、介面與多態 |
1、什麼是介面?
介面是一種規範,提供了一組實作介面的類別所必須實現的方法組合。
介面使用interface關鍵字宣告;
interface Inter{}
2、接口中的所有方法,必須都是抽象方法。
介面中的抽象方法不需要也不能使用abstract修飾。
3、介面中不能宣告變量,不能有屬性,只能使用常數! ! !
4、介面可以繼承接口,使用extends關鍵字!
介面使用extends繼承接口,可以實現多重繼承。
interface int1 extends Inter,Inter2{}
#5、類別可以實作接口,使用implements關鍵字!
類別使用implements實作接口,可同時實作多個接口,多個接口間逗號分隔;
abstract class Person implements Inter,Inter2{}
#一個類別實作一個或多個接口,那麼這個類,必須實作所有接口中的所有抽象方法!
除非,這個類別是抽象類別。
①宣告方式上,介面使用interface關鍵字,抽象類別使用abstract class。
②實作/繼承方式上,一個類別使用extends繼承抽象類,使用implements實作介面。
③抽象類別只能單繼承,介面可以多實作。 (介面extends介面)、多重實作(類別implements介面)
④抽象類別中可以有非抽象方法,介面中只能有抽象方法,不能有費抽象方法。抽象類別中的抽象方法必須使用abstract關鍵字修飾,介面中抽象方法不能帶修飾詞。
⑤抽象類別是個類,可以有屬性、變數;介面中只能有常數。
#二、多態
1、一個類,被多個子類別繼承。
如果,這個類別的某個方法,在多個子類別中,表現出不同的功能,我們稱這種行為為多態。
2、實作多態的必要途徑:
① 子類別繼承父類別;
② 子類別重寫父類別方法;
以上是談談我對php中物件導向的理解的詳細內容。更多資訊請關注PHP中文網其他相關文章!