PHP物件導向(三)

weixin_34007291發表於2018-05-11

前言

下面所講的知識點都是個人從書中和各種教學視訊裡總結出來的一些小知識,可能總結的不是很到位,如果有總結的不對的地方,還希望各位簡友指點...希望這篇文章能夠對初學者有所幫助

本篇文章的學習目標
  • 什麼是介面?
  • 類的自動載入
  • 物件克隆和物件遍歷
  • 單例設計模式

介面技術

1:介面的基本概念?
  • PHP類是單繼承,也就是不支援多繼承。
  • 當一個類需要多個類的功能室,單繼承就不能為力了,為此PHP引入了類的介面技術。
  • 多人合作開發專案時,需要規範各個功能的名稱,就需要用到介面技術。
  • 介面就是一個標準,一個規範。類的功能實現,按照標準介面實現即可;
  • 介面就是特殊的抽象類。可以理解為類的領導者,或者類中方法的目錄大綱。
2:介面定義和實現要點
  • interface 關鍵字定義介面;
  • implements 關鍵字用來實現介面;
  • 類可以繼承類,介面可以使繼承介面,但是類只能實現(implements)介面。
  • 介面的方法許可權必須是public;
  • 介面中方法預設是抽象的,所有不需要再方法名前加abstract;
  • 介面中方法可以使成員方法,也可以是靜態方法;
  • 介面中也可以定義常量,但常量不能重寫
  • 類可以實現(implements)多個介面(相當於把多個功能集於一身,如手機實現了打電話、聽歌、放視訊等功能);
舉個例子:
  //定義Inter1介面
interface Inter1{
  //定義類常量
  const TITLE = '<h2>介面的定義和實現演示</h2>';
  //定義抽象的成員方法,不寫方法體
  public function showInfo();
  }
//定義inter2 介面
interface Inter2 介面
  interface Inter2{
  //定義抽象的靜態方法,不寫方法體
      public static function readMe();
  }
  //建立學生類,並同時實現兩個介面
  class student implements Inter,Inter2{
    //重寫showInfo()抽象方法
      public function showInfo()
            {
              echo __METHOD__."<br>";
                }
      //重寫靜態的readMe()抽象方法
          public static function readMe()
        {
          echo __METHOD__;
            }
    }
      //定義最終的另一個學生類,並繼承上一個學生類
    final class fun_student extends student{}
      //建立新的學生類物件
      $obj = new fun_student();
      $obj->showInfo();
      fun_student::readMe();

類的自動載入

1:為什麼需要類的自動載入?

很多初學者寫物件導向的應用程式時,對每個類的定義,都建立一個獨立的 PHP 原始檔,方便類檔案的統一管理,這無可厚非。但一個很大的煩惱是,不得不在每個指令碼開頭,寫一個長長的包含檔案列表(每個類一個檔案)。這樣一來,就增加了很多負擔、佔用了很多的記憶體,對於後期維護也不方便。
解決辦法:按需要載入類檔案,而不是把所有類全部包含進來.

2:類的常規載入:__autoload()
  • 類的自動載入應用場景

在 PHP 5 中,定義一個 __autoload() 系統函式,它會在試圖使用尚未被定義的類時自動呼叫。通過呼叫此函式,指令碼引擎在 PHP 出錯失敗前有了最後一個機會載入所需的類。
提示:由於__autoload()不太靈活,在以後的版本中它可能被棄用。

  • __autoload()函式詳解

當試圖使用未定義的類時自動呼叫,使用一個類的幾種情況:

  • 使用new關鍵字建立不存在類的物件時,__autoload()自動呼叫;例如:$obj = new Student()
  • 當使用靜態化方式訪問一個不存在的類時,__autoload()自動呼叫,例如:Student::show();
  • 當繼承一個不存在的類時,__autoload()自動呼叫,例如:class Stu extends Parent{}
  • 當實現一個不存在的介面時,__autoload()自動呼叫,例如:class Stu implements Inter

類檔案的命名規範

  • 一個類要單獨定義成一個獨立的類檔案
  • 類副檔名,要以"xxx.class.php"結尾,是一種規範,不是必須的;
  • 類檔案主名,要與類名一致;
  • 例如:Db.class.php --- UserController.class.php
3:類的自定義載入:spl_autoload_register()
  • 為什麼要使用spl_autoload_register()載入類檔案?
  • 如果載入的類檔案,位於不同的目錄中,命名方式也不盡相同,__autoload()就顯得不靈活了。
  • spl_autoload_register()提供了一種更加靈活的方式來實現類的自動載入。
  • 注意:在PHP7中,__autoload()已經被屏棄了。
語法格式
  //語法格式
    spl_autoload_register(func);
    引數:func 引數可以使一個字串的函式名
            func引數可以使一個匿名函式
            func函式程式碼功能,實現類檔案的自動載入過程
      說明:spl_autoload_register()可以多次呼叫,每次呼叫註冊一種類檔案的裝載規則;
  • 使用普通函式作為引數

    //類的自定義載入
    spl_autoload_register("func1");
    spl_autoload_register("func2");
      function fun1($className){
               //構建類檔案的真實路徑
              $filename = "./libs/$className.class.php";
              //如果類檔案存在,則包含
              if(file_exists($filename))require_once($filename);
        }
         function func2($className){
            //構建類檔案的真實路徑
                $filename = "./public/$className.class.php";
             //如果類檔案存在,則包含
            if(file_exists($filename))require_once($filename);
          }
        //建立教師類物件
          $obj1 = new Teacher();
           $obj1->showInfo();
        //建立學生物件
          $obj2 = new student();
            $obj2->showInfo();
    
  • 使用匿名函式作為引數

    //類的自定義載入
    spl_autoload_register(function($classname){
          //構建不同類檔案的真實路徑的陣列
          $arr = array(
                "./libs/$className.class.php",
                "./public/$className.class.php"
                  );
              //迴圈判斷陣列中哪個類檔案路徑有效
              foreach($arr as $filename)
              {
                    //如果類檔案存在,則包含
                      if(file_exists($filename)){
                        require_once($filename);
                          }
                  }
              });
            //建立教師類物件
                  $obj1 = new teacher();
                  $obj1->showInfo();
             //建立學生類物件
                   $obj2 = new student();
                   $obj2->showInfo();
    

物件克隆

1:什麼是物件克隆
  • 如果已存在了一個物件,而還想再建立一個新物件,並且,兩個物件的屬性值不一樣,或者屬性比原來多 ,怎麼實現呢? $obj2 = $obj1 無法實現!
  • $obj2 = $obj1,這不是複製物件,而是將$obj1和$obj2指向了同一個物件地址。
  • 建立新物件有兩種方式:a. 使用new關鍵字; b. 使用 clone 關鍵字
語法格式
  //定義一個學生類
  class student{
            public $name = "小明";
            public $age = 14;
          }
        //建立學生類的物件
        $obj1 = new student;
        //克隆物件
        $obj2 =  clone $obj1;
          var_dump($obj1,$obj2);
2、魔術方法__clone()在克隆物件中的使用
  • 當複製完成時,如果定義了 __clone()方法,則新建立的物件(複製生成的物件)中的 __clone()方法會被呼叫,可用於修改屬性的值(如果有必要的話)。

    //定義一個學生類
    class student
    {
      public $name = "小明";
      public $age = 14;
      //當克隆完成是,__clone()魔術方法自動呼叫
      //在__clone()方法中對新物件進行一些操作.
      public function __clone()
      {
            $this->name = "小紅";
            $this->age = 15;
            $this->edu = "初中";
          }
      }
    //建立學生類的物件
      $obj1 = new student;
      $obj2 = clone $obj1;//克隆物件
      var_dump($obj1,$obj2);
    

物件遍歷

foreach 既可以遍歷陣列元素,也可以遍歷物件屬性;

//定義一個學生類
class student {
        public $name = "小明";
        public $age = 14;
        private $edu = "初中";
        protected $salary = 5000;
    //在類內遍歷物件屬性
        public function showAllAtter(){
          //在類內遍歷物件屬性
          foreach($this as $name=>$value){
                echo "\$this->{name} = {$value}<br>";
                  }
          }
    }
  //建立學生類物件
    $obj = new student;
    $obj->showAllAttrs();
    //在類外輸出的物件屬性
      echo "<h2>在類外輸出的物件屬性</h2>";
      foreach($obj as $name=>$value){
          echo "\$obj->{$name} = {$value}<br>";
        }

從以上程式碼的輸出結果來看,在類外只能輸出public許可權的屬性....在類內可以輸出所有許可權的屬性...

物件導向的設計模式

1:什麼是物件設計模式?

設計模式(Design pattern)是一套被反覆使用多人知曉的、經過分類編目的、程式碼設計經驗的總結。使用設計模式是為了可重用程式碼、讓程式碼更容易被他人理解,保證程式碼可靠性。

2:常用的設計模式有哪些?
  • 單例設計模式:一個類只能建立一個例項物件,不管用什麼辦法都無法建立第2個物件;
  • 工廠設計模式:生產不同類物件的工廠;
  • 策略設計模式:定義一組演算法,將每個演算法都封裝起來,並且使它們之間可以互換。
  • 觀察者設計模式:定義物件間一種一對多的依賴關係,使得每當一個物件改變狀態,則所有依賴於它的物件都會得到通知並被自動更新。
    提示:OOP中設計模式大約有幾十種,可以上百度查。
3:單例模式的設計要求(三私一公)
  • 一私:私有的靜態的儲存物件的屬性;
  • 一私:私有的構造方法,阻止類外new物件;
  • 一私:私有的克隆方法,阻止類外clone物件;
  • 一公:公共的靜態的建立物件的方法;
4:單例設計模式演示
  //單例設計模式的核心程式碼
    class Db
    {
        //私有的靜態的儲存物件的屬性
          public static $obj = NULL;
        //私有的構造方法,阻止類外New物件
            public function __construct(){}
        //私有的克隆方法,阻止類外Clone物件
            public function __clone(){}
         //公共的靜態的建立物件的方法
           public static function getInstance()
          {
                  //判斷當前物件是否存在
                    if(!self::$obj instanceof self)
                      {
                        //如果物件不存在,則建立並儲存它
                          self::$obj = new self;
                          }
                        return self::$obj;
            }
          }
      //建立資料庫的物件
          $db1 = Db::getInstance();
          $db2 = Db::getInstance();
            var_dump($db1,$db2);
      //單例模式不管呼叫多少次,總是一個物件!

結束語

這篇文章只涵蓋了我這幾天所接觸到的物件導向,並沒有完全的總結,後續的學習中在持續更新吧,畢竟這個東西對我來說真的是挺難理解的。總結的可能不好,各位看官就將就著看吧。上面的例子可以複製到編輯器,然後自行檢視效果。

相關文章