PHP基礎教程十之靜態屬性和靜態方法

來源:互聯網
上載者:User

本節講解的內容

  • 靜態屬性和靜態方法

  • 存取修飾詞

  • 單例模式

  • 魔術方法

  • 類的自動載入

前言

在上一節中,我們介紹了物件導向的基本使用,但是上節的知識,在實際中還有問題是解決不了的,比如我們去買票,有一個總票數(定義票這個屬性),來一個人買一張票(票-1),但是我們每次建立一個對象,根據對象在記憶體中的方式,都是重新建立一個總票數,這樣是不合理,這裡我們就使用到了靜態這個概念,在PHP中類中的靜態分為兩種:

  1. 靜態屬性

  2. 靜態方法

靜態屬性

靜態屬性是該類的所有對象共用的變數,任何一個該類的對象去訪問它時,取到的都是相同的值,同樣任何一個該類的對象去修改它時,修改的也是同一個變數

<?php    class Ticket{        public static $number = 100; //設定總的票數是100;        public $name ;         public function __construct($name){            $this-> name = $name;        }        //定義一個方法進行買票        public function sellTicket(){            echo $this-> name . '買票了<br>';            self::$number--; //每調用一次方法總票數就減一。        }    }    $people1 = new Ticket('小白');    $people2 = new Ticket('小明');    $people3 = new Ticket('小華');    $people4 = new Ticket('小張');    //每個人進行買票    $people1 -> sellTicket();    $people2 -> sellTicket();    $people3 -> sellTicket();    $people4 -> sellTicket();    echo Ticket::$number; //在類的外部通過類名訪問靜態屬性。    ......結果........    小白買票了    小明買票了    小華買票了    小張買票了    96

在上面的代碼中可以看到靜態屬性的定義方式。

存取修飾詞  static  $靜態屬性名字 = 初始化值;

靜態屬性只能定義在類的內部。

靜態屬性的訪問

在類外面

在類外面我們也是可以訪問類中的靜態屬性的,就像上面寫的那樣通過類名來直接存取(只有許可權修飾符是public的時候才能這樣)Ticket::$number;其中::是範圍解析符。

在類的外部還可以通過對象來對靜態屬性進行訪問

$people4::$number;

通過類名進行訪問是通過範圍解析符::進行訪問。

在類裡面

上面的代碼中,我們可以看到,在類中我們通過self::$靜態屬性名進行訪問。除了這種方式,在類中還有一種方式來進行訪問。

Ticket::$number--;

通過類名來訪問。而推薦使用的格式是通過self這種方式,因為這種方式當我們的類名改變後,也不用修改。那麼self和$this有什麼區別呢?

$this和self的區別

其實在上節中講到$this,是指向當前的對象的,而這裡的self是指向當前類,一個指向對象,一個指向類,指向不同。同時他們兩個的使用方式不一樣self是兩個::,$this是->。但是它們兩個的適用範圍是一樣的,都是在類的內部使用。

靜態屬性的使用

在上面我們只是講解了靜態屬性的定義方法以及使用方法,至於什麼時候時候需要使用到靜態屬性。當我們在項目開發中,需要讓所有的對象共用一份資料時,我們就考慮使用靜態屬性。

靜態屬性也是一個屬性,那麼它與普通屬性的區別是:

  • 屬性加上static這個關鍵字,就會變成靜態屬性。

  • 靜態屬性的屬於類的,所有對象共用的屬性

  • 普通屬性是屬於單一對象的。

注意,就像上面的一樣,在非靜態方法中可以訪問靜態屬性。

靜態方法

上面講到靜態屬性,那麼接下來就講一講靜態方法。

<?php    class Ticket{        public static $number = 100; //設定總的票數是100;        public $name ;         public function __construct($name){            $this-> name = $name;        }        public static function sayHello(){            echo '這是靜態方法<br>';        }        public function info(){            //在類的內部使用靜態方法            self::sayHello(); //通過self訪問            Ticket::sayHello();//通過類名的方式進行訪問        }    }    $people1 = new Ticket('小白');    $people1 -> info();    $people1::sayHello(); //在類的外部通過對象名進行訪問    Ticket::sayHello();  //通過類型進行訪問。    ......結果........    這是靜態方法    這是靜態方法    這是靜態方法    這是靜態方法

靜態方法的定義方式是通過關鍵字static來定義的:

存取修飾詞 static function 方法名(參數列表){    code....}

靜態方法的訪問

在類外面

靜態方法在類外邊的訪問形式和訪問靜態屬性的方法是一樣的(許可權修飾符只有是public才可以在外部存取)。

  • 通過類名::靜態方法名進行訪問

  • 通過對象名::靜態方法名(不推薦)

  • 通過對象名->靜態方法名。也就是存取方法的形式。

在類裡面

在類裡面訪問靜態方法的方式和訪問靜態屬性的方法也是一樣的

  • self::靜態方法名

  • 類名::靜態方法名

靜態方法的使用

那麼我們在什麼情況下使用靜態方法呢?我們可以在操作靜態屬性的時候使用靜態方法。

  • 當我們需要操作靜態屬性時,我們考慮使用

  • 在我們php開發中,經常會使用到一些模式,比如單例模式,原廠模式,觀察者模式等,都使用使用靜態方法.

注意:靜態方法不能訪問非靜態屬性

存取修飾詞

在上面的代碼中和說明中,我們可以看到不管是在屬性的前面還是在方法的前面都有一個public,這個public就是存取修飾詞其中的一種。存取修飾詞可以說是實現對象封裝的方法。

存取修飾詞的分類及區別

在PHP中存取修飾詞可以分為三中

  1. public 在上面的代碼中我們都是使用的public,使用這種這個關鍵字修飾的屬性和方法,不管在類的內部還是在類的內部都是可以訪問的。

  2. protected(受保護的)如果使用這個關鍵字修飾,那麼在類的外部是不能訪問。只能在類的內部進行訪問。

    <?php    class Cat{        public $name;        protected $age;        public function __construct($name,$age){            $this -> name = $name;            $this -> age = $age;        }    }    $cat = new Cat('小白',4);    echo $cat -> name; //在類的外部存取public    echo '<br>';    echo $cat -> age; //在類的外部存取protected修飾的屬性。......結果.....小白Fatal error: Cannot access protected property Cat::$age in D:\mywamp\Apache24\htdocs\zendstudio\yunsuanfu\xiushifu.php on line 16

    錯誤的資訊是說不能訪問protected修飾的屬性。

  3. private(私人的),只能在類的內部使用,在外部使用會報和上面一樣的錯誤。

這三種,後面兩種看起來作用一樣,都是只能在類內部使用,那又有什麼區別呢?現在看來,並沒有區別,但是學過類的繼承,那麼這兩種還是有區別的。

存取修飾詞的使用:

  • 成員屬性必須制定存取修飾詞,不然會報錯

  • 方法前面可以不寫修飾符,預設是public

  • 靜態屬性可以不指定存取修飾詞,預設是public

單例模式

上面講解到我們什麼時候使用到靜態方法。在一些設計模式中,我們可以使用到靜態方法和靜態屬性。

設計模式:是一套被反覆使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。 毫無疑問,設計模式於己於他人於系統都是多贏的;設計模式使代碼編製真正工程化;設計模式是軟體工程的基石脈絡,如同大廈的結構一樣。(百度)

在開發的時候,我們有這樣的需求,在代碼中我們建立一個對象,但是我們希望在一個項目中,這個對象執行個體只能有一個,不能建立多個對象,從而實現對資料庫等資源的保護。這時候就使用到單例模式。

<?php    class DaoMysql{        public $link; //類比資料庫串連        private static $instance;//當前類的對象。        private function __construct(){            echo '資料庫連接<br>';        }        public static function getInstance(){            if(self::$instance == null){                self::$instance = new DaoMysql();            }            return self::$instance;        }        public function insertSql(){            echo '添加資料<br>';        }    }    $daoMysql = DaoMysql::getInstance();    $daoMysql -> insertSql();    $daoMysql2 = DaoMysql::getInstance();    $daoMysql2 -> insertSql();    ......結果.......    資料庫連接    添加資料    添加資料

1. 既然是單例模式,那麼就不能在外部建立對象,這就要把建構函式用private修飾(建立對象要調用建構函式,這裡把建構函式私人化,調用不起來),這樣在外部就不能建立對象。
2. 我們在類裡面建立了一個對象的引用$instance,在類裡面建立對象,這是允許的。
3. 在類中定義一個靜態方法,我們就是通過這個方法來建立對象,通過類名::方法名進行建立,進去後先判斷$instance是否為空白,只有如空的時候我們才進行建立。然後返回對象。
4. 因為要在靜態方法中訪問屬性,那麼這個屬性就應該是靜態屬性。
5. 在類的外部通過類::靜態方法名進行對象的建立。
6. 在結果中我們可以看到我們有兩個對象,但是構造方法在第二次沒有執行,說明對象沒有建立。

雖然在上面我們做了很多限制,但是在PHP中還是有方法的到更過的對象,複製和繼承。

物件類型運算子

在上面的靜態方法中判斷對象是否建立還有一種方法。

if(!(self::$instance instanceof self)){                self::$instance = new DaoMysql();}

其中instanceof就是類型運算子。 根據協助文檔,它有幾個作用

  1. 用於確定一個 PHP 變數是否屬於某一類 class 的執行個體:

  2. 可用來確定一個變數是不是繼承自某一父類的子類的執行個體:

  3. 也可用於確定一個變數是不是實現了某個介面的對象的執行個體:

上面的代碼中self代表當前的類。instanceof判斷前面的變數是否是後面類的執行個體,然後取反。

魔術方法

在PHP中有一些定義在類中的神奇的方法,稱為魔術方法。具體的魔術的方法的使用可以看另外一篇部落格
PHP的魔術方法

類的自動載入

在前面我們講過檔案的引入,使用include和require這兩種類型。在開發中我們有時需要引入大量的檔案,可以是10個,也可能是20個,如果還是使用原來的方法,累人。

在 PHP 5 中,不再需要這樣了。可以定義一個 __autoload() 函數,它會在試圖使用尚未被定義的類時自動調用
而我們在寫類的時候,一般都是一個類一個檔案,而檔案的名字我們一般是類名.class.php的格式。

<?php    //自動載入的方法,當我們使用這個檔案不存在的類的時候,就會自動載入。    function __autoload($class_name){        require_once './' . $class_name . '.class.php';    }    $dao = new Dao('小白',5);    $cat = new Cat('小花',2);    $dao -> eat();    $cat -> eat();

__autoload($類名),在個函數不是寫在類中的,所以前面是沒有許可權修飾符。

上面的自動載入方式是有局限性的,當檔案是在不同的檔案夾中的時候,這種方法顯然是不行的。這時候可以建立一個數組,把類名當做鍵,對應的路徑當成值,進行儲存。自動載入的時候就能正確的引入。

<?php    $path = array(            'Dao' => './dao/Dao.class.php',            'Cat' => './cat/Cat.class.php'        );    //自動載入的方法,當我們使用這個檔案不存在的類的時候,就會自動載入。    function __autoload($class_name){        global $path;        require_once $path[$class_name];    }    $dao = new Dao('小白',5);    $cat = new Cat('小花',2);    $dao -> eat();    $cat -> eat();

可以看到在前面定義了一個數組用來儲存路徑。
注意:在函數中使用global聲明一下,才能使用全域變數。

總結

在物件導向中用到靜態屬性和靜態方法的時候還是很多的。同時許可權修飾符在物件導向中是很重要的,因為我們通過修飾符控制存取權限。魔術方法的掌握,也可以讓我們在訪問中明白各種調理機制。

以上就是PHP基礎教程十之靜態屬性和靜態方法的內容,更多相關內容請關注topic.alibabacloud.com(www.php.cn)!

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.