本節講解的內容
靜態屬性和靜態方法
存取修飾詞
單例模式
魔術方法
類的自動載入
前言
在上一節中,我們介紹了物件導向的基本使用,但是上節的知識,在實際中還有問題是解決不了的,比如我們去買票,有一個總票數(定義票這個屬性),來一個人買一張票(票-1),但是我們每次建立一個對象,根據對象在記憶體中的方式,都是重新建立一個總票數,這樣是不合理,這裡我們就使用到了靜態這個概念,在PHP中類中的靜態分為兩種:
靜態屬性
靜態方法
靜態屬性
靜態屬性是該類的所有對象共用的變數,任何一個該類的對象去訪問它時,取到的都是相同的值,同樣任何一個該類的對象去修改它時,修改的也是同一個變數
<?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是->。但是它們兩個的適用範圍是一樣的,都是在類的內部使用。
靜態屬性的使用
在上面我們只是講解了靜態屬性的定義方法以及使用方法,至於什麼時候時候需要使用到靜態屬性。當我們在項目開發中,需要讓所有的對象共用一份資料時,我們就考慮使用靜態屬性。
靜態屬性也是一個屬性,那麼它與普通屬性的區別是:
注意,就像上面的一樣,在非靜態方法中可以訪問靜態屬性。;
靜態方法
上面講到靜態屬性,那麼接下來就講一講靜態方法。
<?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才可以在外部存取)。
通過類名::靜態方法名進行訪問
通過對象名::靜態方法名(不推薦)
通過對象名->靜態方法名。也就是存取方法的形式。
在類裡面
在類裡面訪問靜態方法的方式和訪問靜態屬性的方法也是一樣的
靜態方法的使用
那麼我們在什麼情況下使用靜態方法呢?我們可以在操作靜態屬性的時候使用靜態方法。
注意:靜態方法不能訪問非靜態屬性;
存取修飾詞
在上面的代碼中和說明中,我們可以看到不管是在屬性的前面還是在方法的前面都有一個public,這個public就是存取修飾詞其中的一種。存取修飾詞可以說是實現對象封裝的方法。
存取修飾詞的分類及區別
在PHP中存取修飾詞可以分為三中
public 在上面的代碼中我們都是使用的public,使用這種這個關鍵字修飾的屬性和方法,不管在類的內部還是在類的內部都是可以訪問的。
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修飾的屬性。
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就是類型運算子。 根據協助文檔,它有幾個作用
用於確定一個 PHP 變數是否屬於某一類 class 的執行個體:
可用來確定一個變數是不是繼承自某一父類的子類的執行個體:
也可用於確定一個變數是不是實現了某個介面的對象的執行個體:
上面的代碼中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)!