PHP基礎教程九之類與對象

本節講解的內容

  • 類與對象
  • 類的構成
  • 對象的創建
  • PHP垃圾回收機制
  • $this講解

前言

PHP是一個面向對象的編程語言,那麼什麼是面向對象呢?我們爲什麼要面向對象呢?在我們的生活中有很多事物都是對象,比如一個杯子,一個盒子等,它們都有自己特有的特徵,它們都是對象。而我們在開發中的開發也是面向對象編程的。對象是人們要進行研究的任何事物,從最簡單的整數到複雜的飛機等均可看作對象。我們使用面向對象編程可以使我們看問題能夠看得全面,同時也有利於與數據的管理和維護,在PHP中面向對象可以分文兩類,一類是模子,創造對象使用,一類是對象,使用模子創建的起來的,那麼它們兩個有什麼關係呢?

類與對象

類與對象:具有相同特性(數據元素)和行爲(功能)的對象的抽象就是類。因此,對象的抽象是類,類的具體化就是對象,也可以說類的實例是對象,類實際上就是一種數據類型。

也就是說把對象的功能和特徵抽取出來,組成一個類,就好比把一個杯子的模型抽取出來,而我們可以根據這個模型(也就是類)去創建各種杯子(也就是對象)。
那麼類是怎麼定義的呢?對象又是怎麼創建的?

類的組成

<?php

    class Cat{ //定義一個貓類
        public $name; //貓的名字
        public $age;//貓的名字
        public $color;//貓的顏色
        //貓的構造方法
        public function __construct(){

        }

        public function sleep(){
            echo '貓睡覺';
        }

        public function eat(){
            echo '貓喫飯';
        }

    }

上面的就是一個類的基本結構,下面我們詳細的講解每個部分的意義。

  • class 是一個關鍵字,不能修改,表示這是一個類。

  • Cat是類名, 類名寫法是大寫字母開頭,駝峯命名。

類的屬性

屬性: 成員屬性是類的一個組成部分,一般是基本數據類型(整數,字符串等),也可是複合類型(對象、數組) , 資源類型。比如我們前面定義貓類的public $age 就是成員屬性。

可以說每個類都有屬性,類的屬性是一類的特徵,比如說貓可以有名字,年齡,顏色等,這些貓類共有的特徵。在類中這種特徵我們稱之爲屬性,當然我們也可以不定義屬性。這個看自己的需求。

屬性前面的public是一個權限修飾符,在後面會有講解。

成員方法(函數)

在上面的代碼中可以看到在類中還有幾個函數,它們和前面的函數是一樣的,不過是前面多了一個權限控制符。也可以叫做成員方法,這些成員方法就是類中的行爲動作,比如上面的貓類,有睡覺這個行爲,也有喫飯這個行爲,當然你可以自己寫它有什麼行爲。

成員方法的語法:

訪問修飾符  function  函數名(形式參數){
    //函數體;
    //return 返回值;
}
  • 訪問修飾符 , 有三種(public, protected, privte), 默認爲public, 後面我們會詳解
  • 其它部就和我們學的函數一樣了,包括調用機制
  • 參數列表可以有多個,可以是任意類型
  • 對於方法的返回值,這個可以看具體需求。
  • 成員方法是定義在類中的,如果定義在類外就不是這個類的行爲了。

構造函數

上面的貓類中有一個方法,方法名是—__construct(),這是個構造函數,那麼什麼是構造函數?構造函數就是在創建對象的時候,進行初始化數據的方法,比如我們想在創建貓類對象的時候,直接把貓的名字、年齡和顏色給它,就可以使用到構造函數。

public function __construct($name,$age,$color){
            $this-> name = $name;
            $this-> age = $age;
            $this-> color = $color;
}

構造函數的語法是:

public  function  __construct(形式參數){  
    //函數體
}

對於構造函數的方法名__construct(),這個是一個魔術方法,在後面有介紹,其實構造函數還有一種寫法,構造函數的方法名是類的名字:

public function Cat($name,$age,$color){

}

上面的構造方法定義方式也是正確的,但是推薦使用魔術方法的那一種(__construct()),以爲這樣當我們的類名發生改變的時候,不用修改。

注意PHP中類的名字不區分大小寫,但是我們還是要按大小寫來寫。同時構造函數是沒有返回值的。

構造函數需要注意的是:

  • 在一個類中,只能有一個構造函數, 這個是強制要求
  • 構造函數是系統自動調用的,我們不用自己調。
  • 如果我們沒有定義一個構造函數,系統會使用一個默認的構造函數,形式如下:public function
  • __construct(){},所以不管我們有沒有定義構造函數,它都是有構造函數的。

上面的三種情況就是類中大致的內容,在後續我們還會降類中的其他情況。

對象的創建

在上面創建對象的類已經有了,那麼怎麼創建對象呢?

對象創建方法

$cat = new Cat();

創建對象的語法是:

$對象名 = new 類名(參數1,參數2);

類名後面的括號裏的參數是傳遞給類的構造函數的,如果構造函數沒有參數,可以不寫。

  • 對象的命名規範和普通變量一樣,使用駝峯法或者下劃線法均可

  • new也是一個關鍵字,不能修改,表示新創建對象

我們創建對象的目的就是需要操作對象,而操作對象,就是操作對象裏面的屬性和方法。

在上面的類下面寫如下代碼:

//創建對象,傳遞三個參數到構造函數。
$cat = new Cat('小花',12,'black');
//通過對象來訪問對象的屬性
echo $cat -> name;
echo '<br>';
echo $cat -> age;
echo '<br>';
echo $cat -> color;
echo '<br>';
$cat-> sleep();
$cat-> eat();
.....結果......
小花
12
black
貓睡覺
貓喫飯

上面的對象通過->訪問屬性和方法。注意屬性的前面沒有$符號

$對象名->屬性名= 值;
echo  $對象名->屬性名;
'-> ' 稱爲對象運算符.

上面的就是對象的創建和最基本的應用

對象的傳遞類型

當我們把對象的值賦給另外一個變量是,是值傳遞還是引用傳遞?

    //創建一個對象
    $cat = new Cat('小花',12,'black');
    $cat1 = $cat; // 把$cat這個對象賦給$cat1;
    $cat1 -> name = '小白';//利用$cat1這個對象修改對象的名字。
    echo $cat1 -> name; //輸出$cat1對象的名字。
    echo '<br>';
    echo $cat -> name; //輸出$cat對象的名字。
.....結果......
小白
小白

看到這裏可能有點蒙,不是值傳遞嗎?怎麼修改一個對象的屬性,另外一也變了?,

上面的代碼當中 $cat1=$cat也是值傳遞,但是這個值是對象的引用(可以理解對象標識符),即每個包含對象的變量都持有對象的引(reference),而不是整個對象的拷貝。

這裏寫圖片描述

在上面的圖中可以看到,當$cat賦值給$cat1時,也就是對象標識符(#1)複製了一份,賦給$cat1,其實他們還是指向同一塊數據區,所以只要其中一個修改了值,另外一個也會變。

對象的銷燬

我們使用完對象後,已經確定在以後不會使用這個對象了,這個時候我們可以手動的銷燬對象,那麼我們怎麼讓對象銷燬呢?

  1. 當沒有任何變量指向對象時,會銷燬,因此我們可以把對象引用置爲null
  2. 使用unset()函數來銷燬對象。

    //創建一個對象
    $cat = new Cat('小花',12,'black');
    $cat -> sleep();
    unset($cat);
    $cat -> sleep();
    .....結果.....
    
    貓睡覺
    Notice: Undefined variable: cat in D:\mywamp\Apache24\htdocs\zendstudio\yunsuanfu\object.php on line 27
    
    Fatal error: Call to a member function sleep() on null in D:\mywamp\Apache24\htdocs\zendstudio\yunsuanfu\object.php on line 27
    

    其實在一個文件運行完的時候,PHP會啓動垃圾回收機制,自動的進行垃圾回收。這時候在裏面創建的對象就自動銷燬了,那麼什麼是PHP的垃圾回收機制?

PHP垃圾回收機制

垃圾回收,顧名思義,回收垃圾的,在程序中啓動垃圾回收機制的時機:

  • 在php中,當一個對象沒有任何引用指向它的時候,就會成爲一個垃圾對象,php將啓動垃圾回收器將對象銷燬。
  • 當程序退出前,php也將啓用垃圾回收器,銷燬對象。

那麼什麼是垃圾回收機制?

垃圾回收機制是php5之後纔有的,php5.3之前使用的垃圾回收機制是單純的“引用計數”,也就是每個內存對象都分配一個計數器,當內存對象被變量引用時,計數器+1;當變量引用撤掉後,計數器-1;當計數器=0時,表明內存對象沒有被使用,該內存對象則進行銷燬,垃圾回收完成。但是PHP5.3開始,使用了新的垃圾回收機制,在引用計數基礎上,實現了一種複雜的算法,來檢測內存對象中引用環的存在(對象的相互引用),以避免內存泄漏。

$this說明

在上面寫類的構造函數的時候,可以看到在函數中使用到了$this,那麼在面向對象中$this是什麼?

$this是在類中使用的訪問自身的一種機制。系統會給每個對象分配$this,代表當前對象。通俗的說就是在當前環境下,誰調用,$this就代表哪個對象。

<?php

    class Cat{ //定義一個貓類
        public $name; //貓的名字
        public $age;//貓的名字
        public $color;//貓的顏色
        //貓的定義方法
        public function Cat($name,$age,$color){
            $this-> name = $name;
            $this-> age = $age;
            $this-> color = $color;
        }

        public function sleep(){
            echo '貓睡覺<br>';
        }

        public function eat(){
            echo '貓喫飯<br>';
        }
        //輸出貓的信息
        public function info(){
            echo '貓的名字是' . $this -> name . ' 年齡是' . $this-> age . ' 顏色是' . $this-> color;
        }

    }
    //創建一個對象
    $cat = new Cat('小花',12,'black');
    $cat -> info();
    echo '<br>';
    //創建另一個對象,傳進不同的屬性
    $cat1 = new Cat('小白',6,'white');
    $cat1 -> info();
    .....結果.....
貓的名字是小花 年齡是12 顏色是black
貓的名字是小白 年齡是6 顏色是white

在上面的類中的info()函數中使用$this,不同的對象輸出不同的結果,因爲在不同的環境下,誰調用,$this就代表哪個對象。

類的析構函數

在上面我們提到過,對象的銷燬,其實在類中有一個方法,就是在對象銷燬的時候由系統自動執行的。我們稱之爲析構函數。

public function __destruct(){
        echo $this->name . '被銷燬了<br>';
}

在PHP5中引入了析構函數的概念,析構函數會在某個對象的所有引用被刪除(沒有變量指向對象,要被銷燬了),對象銷燬前執行。

析構函數的主要作用是去釋放對象分配的相關資源,比如數據庫連接或打開的文件等。

它的語法是:

function  __destruct(){
    //函數體[釋放資源,比如數據庫連接,或者打開文件等等]
}

析構函數也是系統自動調用的,我們不用自己調。但是當我們沒有寫析構函數的時候,系統不會執行析構函數。

<?php

class Cat{ //定義一個貓類
    public $name; //貓的名字
    public $age;//貓的名字
    public $color;//貓的顏色
    //貓的定義方法
    public function Cat($name,$age,$color){
        $this-> name = $name;
        $this-> age = $age;
        $this-> color = $color;
    }

    public function sleep(){
        echo '貓睡覺<br>';
    }

    public function eat(){
        echo '貓喫飯<br>';
    }
    //輸出貓的信息
    public function info(){
        echo '貓的名字是' . $this -> name . ' 年齡是' . $this-> age . ' 顏色是' . $this-> color;
    }

    public function __destruct(){
        echo $this->name . '被銷燬了<br>';
    }

}
//創建一個對象
$cat = new Cat('小花',12,'black');
echo $cat -> name; //輸出對象的名字
echo '<br>';
unset($cat); //銷燬對象,系統自動調用析構函數。
.....結果......
小花
小花被銷燬了

當我們銷燬對象$cat時,析構函數自動執行。

  • 析構函數是在對象銷燬前自動執行的,它沒有返回值。切一個類中只能有一個析構函數。
  • 析構函數是銷燬對象創建的資源,不是銷燬對象本身,對象本身是由垃圾回收機制銷燬的。

當我們一個文件中創建了多個對象,在文件執行完畢,銷燬對象的時候,是先創建的對象後銷燬,後創建的對象,先銷燬,這個原理和棧的原理很想,先進後出,後進先出。

總結

通過上面對類和對象的講解,我們可以知道類和對象的區別和聯繫。類是抽象的,代表着一類事物,如貓類。對象時具體的,代表一個具體事物。類是對象的模板,對象是類的一個個實例。同時類的基本構成要掌握。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章