PHP物件導向實用基礎知識

炎欲天舞
發布: 2023-03-14 16:14:01
原創
1602 人瀏覽過


一、物件導向基礎
################## ######

 

物件導向

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進行私有化處理。


private function formatName(){} //这个方法仅仅能在类内部使用$this调用
function showName(){
    $this -> formatName();
}
登入後複製

②屬性的封裝+set/get方法
為了控制屬性的設定以及讀取,可以將屬性進行私有化處理,並要求使用者透過我們提供的set/get方法進行設定


#
 private $age;
 //set方法
 function setAge($age){
     $this->age=$age;
 }
 //get方法
 function getAge(){
     return $this->age;
 }
登入後複製

$物件->getAge() ;
$物件->setAge(12);

#③屬性的封裝+魔術方法


#
private $age;
function __get($key){
return $this->$key;
}
function __set($key,$value){
$this->$key=$value;
}
登入後複製

$物件->age; //存取物件私有屬性時,自動呼叫__get()魔術方法,並且將存取的屬性名稱傳給__get()方法;
$物件->age=12; //設定物件私有屬性時,自動呼叫__set()魔術方法,並且將設定的屬性名稱以及屬性值傳給__set()方法;

注意:在魔術方法中,可以使用分支結構,判斷$key的不同,進行不同操作。

 

4、關於封裝的魔術方法:
①__set($key,$value):給類別私有屬性賦值時自動調用,調用時給方法傳遞兩個參數:需要設定的屬性名,屬性值。
②__get($key,$value):讀取類別私有屬性時自動調用,呼叫時給方法傳遞一個參數,需要讀取的屬性名稱;
③__isset($key):外部使用isset()函數偵測私有屬性時,自動呼叫。
>>>類別外部使用isset();偵測私有屬性,預設是偵測不到的。 false
>>>所以,我們可以使用__isset();函數,在自動呼叫時,回傳內部偵測結果。


 function __isset($key){
     return isset($this -> $key);
 }
登入後複製

當外部使用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::方法名();
所以,当子类继承父类时,需在子类的构造中的第一步,首先调用父类构造进行复制。


 function __construct($name,$sex,$school){
     partent::__construct($name,$sex);
     $this -> school = $school;
 }
登入後複製

三、PHP关键字

1、final
①final修饰类,此类为最终类,不能被继承!
②final修饰方法,此方法为最终方法,不能被重写!
③final不能修饰属性。

2、static
①可以修饰属性和方法,分别称为静态属性和静态方法,也叫类属性,类方法;
②静态属性,静态方法,只能使用类名直接调用。
使用"类名::$静态属性" , "类名::静态方法()"
Person::$sex; Person::say();
③静态属性和方法,在类装载时就会声明,先于对象产生。
④静态方法中,不能调用非静态属性或方法;
非静态方法,可以调用静态属性和方法。
(因为静态属性和方法在类装载时已经产生,而非静态的属性方法,此时还没有实例化诞生)
⑤在类中,可以使用self关键字,代指本类名。


 class Person{
     static $sex = "nan";
     function say(){
         echo self::$sex;
     }
 }
登入後複製

⑥静态属性是共享的,也就是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个)

clone与__clone


1、当使用=讲一个对象,赋值给另一个对象时,赋的实际是对象的地址。
两个对象指向同一地址,所以一个对象改变,另一个也会变化。
eg: $lisi = $zhangsan;
2、如果想要将一个对象完全克隆出另一个对象,两个对象是独立的,互不干扰的,
则需要使用clone关键字;
eg: $lisi = clone $zhangsan; //两个对象互不干扰
3、__clone():
①当使用clone关键字,克隆对象时,自动调用clone函数。
②__clone()函数,类似于克隆时使用的构造函数,可以给新克隆对象赋初值。
③__clone()函数里面的$this指的是新克隆的对象
某些版本中,可以用$that代指被克隆对象,绝大多数版本不支持。
4、__toString()
当使用echo等输出语句,直接打印对象时调用echo $zhangsan;
那么,可以指定__toString()函数返回的字符串;


 function __toString(){
     return "haha";
 }
 echo $zhangsan; //结果为:haha
登入後複製

5、__call()
调用类中未定义或未公开的方法时,会自动执行__call()方法。
自动执行时,会给__call()方法传递两个参数;
参数一:调用的方法名
参数二:(数组)调用方法的参数列表。

__antoload()


①这是唯一一个不在类中使用的魔术方法;
②当实例化一个不存在的类时,自动调用这个魔术方法;
③调用时,会自动给__autoload()传递一个参数:实例化的类名
所以可以使用这个方法实现自动加载文件的功能。


 function __autoload($className){
 include    "class/".strtolower($className).".class.php";
 }
 $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中,型別約束,只能發生在函數的形參中。


#
 class Person{}
     class Student extends Person{}
     function func(Person $p){ //约束函数的形参,只接受Person类及Person子类
     echo "1111";
     echo $p -> name;
 }
登入後複製

func(new Person());
func(new Student());
func("111"); ×

形如new Person();的形式,我们称其为"匿名对象";

※※※基类:父类    
※※※派生类:子类

魔术方法小总结


1、__construct():构造函数,new一个对象时,自动调用。
2、__destruct():析构函数,当一个对象被销毁前,自动调用。
3、__get():访问类中私有属性时,自动调用。传递读取的属性名,返回$this->属性名
4、__set():给类的私有属性赋值时,自动调用。传递需要设置的属性名和属性值;
5、__isset():使用isset()检测对象私有属性时,自动调用。传递检测的属性名,返回isset($this -> 属性名);
6、__unset():使用unset()删除对象私有属性时,自动调用。传递删除的属性名,方法中执行unset($this -> 属性名);
7、__toString():使用echo打印对象时,自动调用。返回想要在打印对象时,显示的内容;返回必须是字符串;
8、__call():调用一个类中未定义或未公开的方法时,自动调用。传递被调用的函数名,和参数列表数组;
9、__clone():当使用clone关键字,克隆一个对象时,自动调用。作用是为新克隆的对象进行初始化赋值;
10、__sleep():对象序列化时,自动调用。返回一个数组,数组中的值就是可以序列化的属性;
11、__wakeup():对象反序列化时,自动调用。为反序列化新产生的对象,进行初始化赋值;
12、__autoload():需要在类外部声明函数。当实例化一个未声明的类时,自动调用。传递实例化的类名,可以使用类名自动加载对应的类文件。

 

六、抽象类和抽象方法

 

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中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板