|
|
本篇文章針對PHP做物件導向程式設計的教學,包含實作範例。
首先建立一個類別名稱,並用中括號{}規範其範圍,建立完類別MyClass後,新增一個變數$obj將類別實例化, 再將變數用var_dump來檢視其內容,- <?php
- class MyClass
- {
- // 類別屬性及方法在此
- }
- $obj = new MyClass;
- var_dump($obj);
- ?>
複製代碼 結果會顯示, 新視窗看結果, 耶!第一個物件導向的例子完成了!- object(MyClass)#1 (0) { }
複製代碼 定義類別屬性
要新增資料到類別裡, 屬性及特定類別變數都會用到, 就像一般變數一樣, 只是會依賴著物件,public會決定此變數的公開程度, echo時,利用箭頭符號->來引用(調用)物件的方法或屬性- <?php
-
- class MyClass
- {
- public $prop1 = "我是類別屬性!";
- }
-
- $obj = new MyClass;
- echo $obj->prop1; // 輸出屬性
-
- ?>
複製代碼 結果會顯示, 新視窗看結果 定義類別方法
方法是特定類別的函式,定義了物件活動的呈現方式, 範例中新增了兩個方法"設定屬性"與"取得屬性",來存取$prop1, OOP允許物件使用$this來引用他自己, 在方法裡使用$this就好比在類別外面的物件名稱($obj)一樣, 此範例會先取得屬性值, 接著給他新值, 再echo一次觀察變化…- <?php
-
- class MyClass
- {
- public $prop1 = "我是類別屬性!";
-
- public function setProperty($newval)
- {
- $this->prop1 = $newval;
- }
-
- public function getProperty()
- {
- return $this->prop1 . "<br />";
- }
- }
- $obj = new MyClass;
- echo $obj->getProperty(); // 取得屬性值
-
- $obj->setProperty("我是新的類別屬性值!"); // 設定新值
- echo $obj->getProperty(); // 再顯示一次屬性值
-
- ?>
複製代碼 結果會顯示, 新視窗看結果, 當然可以新增$obj2,$obj3,$obj4, OOP方便讓物件可以維持個別的實體。 Magic Method
PHP的一系列Magic Method包含 __construct, __destruct, __call, __callStatic, __get, __set, __isset, __unset, __sleep, __wakeup, __toString, __set_state 和 __clone, 以兩行底線做區別, PHP網站的中文翻做魔術方法有點詭異。
使用建構子與解構子
Constructor以及Destructor, 一個類別往往有許多初始化時要做的事情, 因此PHP提供 __construct方法, 讓類別被實例化時, 就會自動執行!- <?php
- class MyClass
- {
- public $prop1 = "我是類別屬性!";
- public function __construct()
- {
- echo '類別 "', __CLASS__, '" 初始化!<br />';
- }
- public function __destruct()
- {
- echo '類別 "', __CLASS__, '" 被釋放.<br />';
- }
- public function setProperty($newval)
- {
- $this->prop1 = $newval;
- }
-
- public function getProperty()
- {
- return $this->prop1 . "<br />";
- }
- }
- $obj = new MyClass;
- echo $obj->getProperty(); // 取得屬性值
-
- unset($obj); // 釋放物件
-
- echo "到最底端了!<br />";
-
- ?>
複製代碼 當類別被實例化時, 會執行__construct, __CLASS__ 會回傳被呼叫建構子所屬的類別名稱; 當程式碼到底端時, __desturct會釋放所有資源, 也可以使用unset提前觸發! 結果會顯示, 新視窗看結果。- 類別 "MyClass" 初始化!
- 我是類別屬性!
- 類別 "MyClass" 被釋放.
- 到最底端了!
複製代碼 轉換成字串
如果新增了一個物件$obj之後, 直接echo $obj; 會發生fatal error錯誤訊息!告知類別無法轉換成字串,所以透過__toString方法, 就可以指定echo直接輸出的內容。- Catchable fatal error: Object of class MyClass could not be converted to string in /OOP_Magc_Method_String.php on line xx
複製代碼- <?php
- class MyClass
- {
- public $prop1 = "我是類別屬性!";
- public function __construct()
- {
- echo '類別 "', __CLASS__, '" 初始化!<br />';
- }
- public function __destruct()
- {
- echo '類別 "', __CLASS__, '" 被釋放.<br />';
- }
- public function __toString()
- {
- echo "使用 toString 方法: ";
- return $this->getProperty();
- }
- public function setProperty($newval)
- {
- $this->prop1 = $newval;
- }
- public function getProperty()
- {
- return $this->prop1 . "<br />";
- }
- }
- $obj = new MyClass;
- echo $obj->getProperty(); // 取得屬性值
- echo $obj; //直接輸出類別
- unset($obj); // 釋放物件
- echo "到最底端了!<br />";
- ?>
複製代碼 範例中__toString() return了getProperty的結果, 新視窗看結果- 類別 "MyClass" 初始化!
- 我是類別屬性!
- 使用 toString 方法: 我是類別屬性!
- 類別 "MyClass" 被釋放.
- 到最底端了!
複製代碼 使用類別繼承
使用extend關鍵字, 就可以將一個類別的方法及屬性遺傳給令一個類別(遺傳的意思好像比較正確), 範例新增了一個MyNewClass類別繼承自MyClass,同樣的方法再寫一次就會覆寫. 因此覆寫了__construct()方法, 繼承了__toString(), setPreperty(), getProperty(), 新增了newMethod()方法; 為了保留父類別已經被覆蓋的方法, 可使用parent關鍵字加上兩個冒號::(scope resolution operator)來取得。- <?php
- class MyClass
- {
- public $prop1 = "我是類別屬性!";
- public function __construct()
- {
- echo '類別 "', __CLASS__, '" 初始化!<br />';
- }
- public function __destruct()
- {
- echo '類別 "', __CLASS__, '" 被釋放.<br />';
- }
- public function __toString()
- {
- echo "使用 toString 方法: ";
- return $this->getProperty();
- }
- public function setProperty($newval)
- {
- $this->prop1 = $newval;
- }
- public function getProperty()
- {
- return $this->prop1 . "<br />";
- }
- }
- class MyNewClass extends MyClass
- {
- public function __construct()
- {
- parent::__construct(); // 呼叫父類別的建構子
- echo "新建構子 " . __CLASS__ . ".<br />";
- }
- public function newMethod()
- {
- echo "新方法 " . __CLASS__ . ".<br />";
- }
- }
- $newobj = new MyNewClass;
- echo $newobj->newMethod(); //輸出字串
- echo $newobj->getProperty(); //使用父類別的方法
- ?>
複製代碼 範例中的結果, 新視窗看結果- 類別 "MyClass" 初始化!
- 新建構子 MyNewClass.
- 新方法 MyNewClass.
- 我是類別屬性!
- 類別 "MyClass" 被釋放.
複製代碼 分配方法與屬性的可見度
為了要控制許多物件, 方法與屬性都被指定了可以存取的程度, 包含public、protected、private三種關鍵字, 除了本身的可見度以外, 方法與屬性也可宣告為Static, 不用透過類別實例化就可以存取。
1.Public – 所有的屬性與方法可以再任何地方被存取,包含內部class與外部呼叫。
2.Protected – 受保護的屬性與方法只能被他自己以及衍生類別存取。- <?php
- class MyClass
- {
- public $prop1 = "我是類別屬性!";
- public function __construct()
- {
- echo '類別 "', __CLASS__, '" 初始化!<br />';
- }
- public function __destruct()
- {
- echo '類別 "', __CLASS__, '" 被釋放.<br />';
- }
- public function __toString()
- {
- echo "使用 toString 方法: ";
- return $this->getProperty();
- }
- public function setProperty($newval)
- {
- $this->prop1 = $newval;
- }
- protected function getProperty()
- {
- return $this->prop1 . "<br />";
- }
- }
- class MyNewClass extends MyClass
- {
- public function __construct()
- {
- parent::__construct(); // 呼叫父類別的建構子
- echo "新建構子 " . __CLASS__ . ".<br />";
- }
- public function newMethod()
- {
- echo "新方法 " . __CLASS__ . ".<br />";
- }
- public function callProtected()
- {
- return $this->getProperty();
- }
- }
- $newobj = new MyNewClass;
- echo $newobj->callProtected(); //從一個public方法內呼叫protected的方法
- ?>
複製代碼 範例中MyNewClass先新增一個方法callProtected()去取得父類別的getProperty(),結果如下新視窗看結果- 類別 "MyClass" 初始化!
- 新建構子 MyNewClass.
- 我是類別屬性!類別 "MyClass" 被釋放.
複製代碼 3.Private – 私有的屬性與方法只定義它的類別可存取,就算是衍生類別也不行。
4.Static – 不需要透過第一次類別實例化,透過類別名稱、雙帽號、屬性或方法就能存取。- <?php
- class MyClass
- {
- public $prop1 = "我是類別屬性!";
- public static $count = 0;
- public function __construct()
- {
- echo '類別 "', __CLASS__, '" 初始化!<br />';
- }
- public function __destruct()
- {
- echo '類別 "', __CLASS__, '" 被釋放.<br />';
- }
- public function __toString()
- {
- echo "使用 toString 方法: ";
- return $this->getProperty();
- }
- public function setProperty($newval)
- {
- $this->prop1 = $newval;
- }
- protected function getProperty()
- {
- return $this->prop1 . "<br />";
- }
- public static function plusOne()
- {
- return "The count is " . ++self::$count . ".<br />";
- }
- }
- class MyNewClass extends MyClass
- {
- public function __construct()
- {
- parent::__construct(); // 呼叫父類別的建構子
- echo "新建構子 " . __CLASS__ . ".<br />";
- }
- public function newMethod()
- {
- echo "新方法 " . __CLASS__ . ".<br />";
- }
- public function callProtected()
- {
- return $this->getProperty();
- }
- }
- do
- {
- // 不實例化就直接呼叫 plusOne()
- echo MyClass::plusOne();
- } while ( MyClass::$count < 10 );
- ?>
複製代碼 範例中有個迴圈會呼叫plusOne()進行計數, 直到$count小於10, 沒有實例化就直接呼叫, 結果如下新視窗看結果- The count is 1.
- The count is 2.
- The count is 3.
- The count is 4.
- The count is 5.
- The count is 6.
- The count is 7.
- The count is 8.
- The count is 9.
- The count is 10.
複製代碼
最後這篇文章還比較並舉例Procedural和OOP的不同,統整了物件導向程式設計的優點:
1.容易實作
2.方便組織
3.更好維護 |
|