PHP 物件導向概念

1 篇文章 / 0 new
author
PHP 物件導向概念
紅色斜體字表你在寫程式碼時須自行替換為合法的識別字

■ Classes and Objects
◆ declare class
[語法]
class ClassName {
          // members,包括  methods(或稱 functions)、 data member(指 properties) 等
         ...........
}

[說明]
定義類別需使用關鍵字「class」,後面指定「類別名稱」,並在大括號「{ }」內定義組成類別的成員。
類別名稱為英文字母部分不區分大小寫,否則會產生 redeclare 錯誤。如 class ABC 與 class aBc 為重複宣告。

[範例]
// 類別
class TestClass {
          function __construct() {                   // 建構子
                      echo "建構子... <br>";
          }
          function __destruct() {                   // 解構子
                       echo "解構子... <br>";
          }
          public function myMethod() {                   // 方法
                       echo "方法... <br>";
          }
          public $myProperty = "屬性... <br>";              // 屬性
}
$obj = new TestClass();                         // 建立實體
echo $obj->myProperty;                          // 呼叫屬性
$obj->myMethod();                            // 執行方法
unset($obj);                                        // 釋放實體

[範例]
class MyClass {
            var $myVar1, $myStatus;                        // OK
            $myVar2;                                //   parse error, unexpected T_VARIABLE, expecting T_FUNCTION
            public $myVar3;                     // OK
}

■ Member
◆ Member Variables (Properties)
1. class 內的 member variables 必須使用 var 關鍵字或使用 private/protected/public 關鍵字宣告。
2. 宣告 property 的動作為可選擇性的,你可以在任何時刻加入新的 property。
3. property 可指派初值(default value),但初值必須為常數(simple constant)。

[範例]
class Person {
              function get_name (  ) {
                            return $this->name;
              }
              function set_name ($new_name) {
                            $this->name = $new_name;
              }
}

[範例] 類別內的 properties 指派初值
var $name = 'J Doe';               // works
var $age  = 0;                     // works
var $day  = 60*60*24;              // doesn't work


⊙ Class Constants
1. to the class and not to instances of the class. Class constants are always case-sensitive
2. constants are constant and can be neither changed nor removed after they are defined.
    Common uses for constants are defining enumerations or some configuration value such as the database username, which you wouldn't want the application to be able to change.
3. 常數前不能加 access modifiers

[範例]
class MyColorEnumClass {
            const RED = "Red";
            const GREEN = "Green";
            const BLUE = "Blue";

            function printBlue() {
                        print self::BLUE;
            }
}
print MyColorEnumClass::RED;
$obj = new MyColorEnumClass();
$obj->printBlue();


◆ Member Functions (Methods) 和 Data Members
method 為定義在 class 內的 function

[範例] function 可傳回物件
class MyClass {
              function M( ) {
                          print "Hello World";
              }
}
function F( ) {
                      return new MyClass;
}
F( )->M( );          // Hello World

[範例]
class Person {
              var $name;
              function get_name (  ) {
                            return $this->name;
              }
        function set_name ($new_name) {
                            $this->name = $new_name;
              }
}

⊙ Final Functions
 method 若宣告為 final 則不能被 overridden

[範例]
class MyBaseClass {
           final function myFinalFunc() {
                      .......
           }
}


◆ Static Member
1. 關鍵字「static」可定義靜態成員,static 前可指定存取限制為 private、protected、或 public。
2. 靜態成員與類別(class) 有關聯,與實體(instance) 為獨立關係,各實體取得靜態變數的值結果相同。
3. 類別外,或類別內的函數要取得靜態成員,可使用「class-name::$static-member」
    同一類別內的函數在存取時,可使用另一種方式「self::$static-member」
4. static properties 無法經由 object 使用 -> 運算子存取
    A)  $object->static-property                           →error
          Calling non-static methods statically generates an E_STRICT level warning (????測試結果只是未顯示東西,無錯誤信息出現)

     B) 但允許使用 -> 運算子存取 static function
            $object->static-method                           →OK

     未宣告成 static 的方法可使用 class-name::$non-static-function 的方式呼叫,但是該 function 裏不能有 $this,否則會產生錯誤
5. call a parent's static method by using the parent:: notationn


[範例]
class MyClass {
           static $myStaticVariable;
           static $myInitializedStaticVariable = 0;
}
MyClass::$myInitializedStaticVariable++;
print MyClass::$myInitializedStaticVariable;                       // 1

[範例]
class MyClass {
           static $myInitializedStaticVariable = 5;

           function myMethod( ) {
                      print self::$myInitializedStaticVariable;                // 或 print MyClass::$myInitializedStaticVariable;
           }
           static function myStaticMethod_PrintHelloWorld( ) {
                      print "Hello, World";
                      self::myStaticMethod_PrintNewline( );
           }
       static function myStaticMethod_PrintNewline( ) {
                      print "<br>";
           }
}
$obj = new MyClass();
$obj->myMethod();               // 5
MyClass::myStaticMethod_PrintHelloWorld();

[範例]
class MyClass {
            function non_static( ) {
                         echo "Non-Static Method ! ";
            }
            static function static_method( ) {
                         echo "Static Method ! ";
                         self::non_static( );             // OK
            }
}
$t = new MyClass();
$t->static_method();             // OK
MyClass::non_static();

■ create instance
建立類別的實體∕物件(instance∕object) 需使用「new」關鍵字。

[範例]
class MyPerson {
           // properties
           private $name;

           // methods
           function setName($name) {
                      $this->name = $name;
           }
           function getName() {
                      return $this->name;
           }
};
// create instances
$classmate1 = new MyPerson();
$classmate1->setName("John");
$classmate2 = new Person();
$classmate2->setName("Joe");
print $classmate1->getName() . "<br>";
print $classmate2->getName(). "<br>";


■ 成員呼叫
1. 使用物件的成員須使用 ->  運算子
 [語法]
 $object->property-name
 $object->method-name([arg, ... ])

2. 未建立類別的物件(object instance)前,可使用 :: 操作符號直接引用類別內的方法。
 [語法]  class-name :: method-name

[範例]
class MyClass {
            var $myVar = 'Non-Static Property ... <br>' ;
            static public $myStaticVar = 'Static Property ... <br>';

            function non_static_method_1() {
                         echo 'Non-Static Method ! <br>';
            }
            function non_static_method_2() {
                         $this->myVar = 'set $myVar property ...';
                         echo '$this->myVar' . $this->myVar . '<br>';
                         echo 'Non-Static Method ! <br>';
            }
            static function static_method() {
                         echo 'Static Method ! <br>';
                         self::non_static_method_1();             // OK
                         self::non_static_method_2();
            }
}
$t = new MyClass();
print '$t->myStaticVar :'.$t->myStaticVar;                       // 顯示「$t->myStaticVar :」
MyClass::non_static_method_1();                       // Non-Static Method !
MyClass::non_static_method_2();                       // Fatal error:  Using $this when not in object context
print MyClass::$myVar;                       // Fatal error:  Access to undeclared static property:  MyClass::$myVar



■ 存取修飾子 (Access Modifier -public∕private∕protected)
property 或 method 可使用存取修飾子控制存取權限。
    ‧public        可由類別內部或外部存取。預設值。
    ‧protected        只能由類別內部或衍生類別所呼叫。
    ‧private        只能由類別內部存取。設定為 private 的 member 不能被繼承,衍生類別無法呼叫。


[範例] public
class A {
             public $p;
             public function m( ) {
                          print "Class A ...";
             }
}
class B extends A {
             public function m( ) {
                          print "Class B ...";
             }
}
$obj = new B;
$obj->p = "Hello World!";
print $obj->p;            // Hello World!

[範例] private
class MyClass {
           private $id = 18;
       public function getId() {
                      return $this->id;
          }
}
$obj = new MyClass;
$obj->id = "SN 566002-5698";              // Fatal error:  Cannot access private property MyClass::$id

[範例] call private property inherited from another class
class X {
           private $Name;
}
class Y extends X { }
$obj = new Y;
$obj->Name = "Joe";
$obj->Name2 = "Jolin";
print_r($obj);
/* 執行結果
   Y Object
   (
         [Name:private] =>
         [Name] => Joe
         [Name2] => Jolin
   )
*/


■ Constructor (建構子)
建構子會在物件產生時(使用 new 關鍵字) 自動執行。建構子可接受參數,且必須宣告為 public。
建構子無法傳回值(return a value)。可藉由丟出 exception 做錯誤處理。

[方法一] 定義一個與 class 同名的 member function,可接受參數。

[方法二] 定義 __construct 方法 (PHP 5+ 版本)
       void __construct ( [mixed args [, ...]] )


[範例]
class Person {
           function __construct($name) {
                      $this->name = $name;
           }
           function getName() {
                      return $this->name;
           }
           private $name;
}
$classmate1 = new Person("John");
$classmate2 = new Person("Joe");
print $classmate1->getName() . "<br>";
print $classmate2->getName() . "<br>";


◆ Calling Parent Constructor
建立 derived class 的物件時,parent class 的 constructor 不會自動被執行(PHP 沒有建構子串接機制,Cascading Constructors),子類別的建構子會完全覆載父類別的建構子,若須要父類別參與物件初始作業的處理,須在子類別的建構子中呼叫父類別的建構子。

[語法] parent::__construct(...)

[範例]
class BaseClass {
             function __construct() {
                          print "In BaseClass constructor <br>";
             }
}
class SubClass extends BaseClass {
             function __construct() {
                          parent::__construct();
                          print "In SubClass constructor <br>";
             }
}
$obj = new BaseClass();
$obj = new SubClass();



■ Destructor 解構子(PHP 5+)
void __destruct ( void )
解構子為物件被釋放時會自動被呼叫的特殊函數,該函數不能定義參數。
解構子內若試圖丟出 exception 會產生 fatal error。
呼叫 parent class 的 destructor 須另外使用「parent::__destruct(...)」呼叫。

[範例]
class MyClass  {
           function __destruct() {
                      print "An object of type MyClass is being destroyed.";
           }
}
$obj = new MyClass();
$obj = NULL;



■ 生存空間 (Scope)
‧ PHP 的生存空間有:
 1) 全域生存空間 (Global Scope)
 2) 局部生存空間 (Local Scope)
   a) 類別生存空間 (Class Scope)
   b) 函式生存空間 (Function Scope)
‧任何一個生存空間中所定義的函式或變數,對其它空間來說都是屬於不可見的(會被隱藏)
 如函式 X 的生存空間,對於函式 Y 的生存空間是屬於不可見的。


■ Accessing Methods and Properties Using the $this Variable
1. 每個類別都有一個 $this 變數(pseudo-variable) 表示該類別本身的物件。
2. 任何一個 method 內(包括建構子),變數 $this 都會參照(reference) 到呼叫目前 method 的物件。
 藉由 $this 變數配合符號 -> 可在 method 內呼叫或存取同一個類別裡的其它成員,亦即去存取歸屬於目前物件的 properties、或呼叫目前物件的其它 methods,以便讓類別成員相互之間可以進行互動。
3. 在 static methods 內並沒有定義 $this 變數。

[範例]
class A {
         function foo() {
                   if (isset($this)) {
                             echo '$this is defined (';
                             echo get_class($this);
                             echo ") <br>";
                   } else {
                             echo "\$this is not defined. <br>";
                   }
         }
}
class B {
         function bar() {
                   A::foo();
         }
}
$a = new A();
$a->foo();
A::foo();
$b = new B();
$b->bar();
B::bar();

■ Cloning Objects (請注意等號&下底線數目)
1. PHP4 使用指派運算子(=) 可複製(copy)物件;使用傳參考方式,會指向(point to)相同的物件。
2. PHP5 將指派運算(=) 視為傳參考,會指向相同的物件。若要複製物件,須使用「clone」關鍵字。
        使用 clone 複製物件時,會先搜尋該物件是否有定義 __clone 方法,並依照該方法的定義內容來複製物件;否則會自動複製每個屬性(copy each member variable)。
        __clone 方法無法直接透過物件呼叫。
3. 運算子「===」可檢驗判別變數是否指向相同物件。

[範例] PHP 4
$var1 = $object;                     // $var1 與 $object 是不同物件
$var2 = &$object;            // $var2 與 $object 是相同物件

[範例] PHP 5
$var1 = $object;                     // $var1 與 $object 是相同物件
$var2 = clone $object;            // $var2 與 $object 是不同物件

[範例]
class MyClass {
        public $var = 1;
}
$obj1 = new MyClass();
$obj2 = $obj1;
$obj2->var = 2;
print $obj1->var;                    // PHP4 --> 1 ; PHP5 --> 2
$obj3 = clone $obj1;
$obj3->var = 5;
print $obj1->var;                    // PHP5 --> 2

[範例] new object to not point at the same file handle, but to open a new one itself so that it has its own private copy
class MyFile {
        function setFileName($file_name) {
                  $this->file_name = $file_name;
        }
        function openFileForReading() {
                  $this->file_handle = fopen($this->file_name, "r");
        }
        function __clone() {
                  if ($this->file_handle) {
                             $this->file_handle = fopen($this->file_name, "r");
              }
    }
    private $file_name;
    private $file_handle = NULL;
}


■ Inheritance
1. 使用「extends」關鍵字可建立繼承關係。
2. 被繼承的類別稱為基底類別(base class)、父類別或超類別(superclass);繼承基底類別的新類別稱為子類別(subclass)、衍生類別(derived class)或擴充類別。
3. PHP 無法同時繼承多個類別,亦即不允許多重繼承。
4. 繼承機制作用在於不須重建已存在於父類別的

[範例]
class A {
          ......
}
class B extends A {
          ......
}


■ Overriding Methods (Redefined Functions)
1. PHP 允許在 subclasses 內重覆定義同名的函式,稱為方法的覆寫(Overriding)。
2. 呼叫 parent class 被覆寫的 method :
 [語法一] 使用父類別名稱呼叫
     superclass-name::method-name
 [語法二] 使用關鍵字 parent 呼叫 (此種方式不須牢記父類別名稱)
     parent::method-name

[範例]
class MyA {
          function info( ) {
                    return "MyA ...";
          }
}
class MyB extends MyA {
          function info( ) {
                    return parent::info( )."MyB ...";
          }
}
class MyC extends MyB {
          function info( ) {
                    return MyA::info( ) . MyB::info( ) . "MyC ...";
          }
}
$objA = new MyA;
$objB = new MyB;
$objC = new MyC;
print $objA->info( );              // prints "MyA ..."
print $objB->info( );              // prints "MyA ...MyB ..."
print $objC->info( );              // prints "MyA ...MyB ...MyC ..."



■ Objects Within Objects
PHP 允許在 object 內含其它 object。
存取物件內的物件須使用關鍵字「new」建立欲存取之類別的物件。

[範例]
class FClass {
          public function myFunc( ) {
                    print "Hello World.";
          }
}
class A {       
          public $var;       
        }
$myObj = new A;
$myObj->var = new FCLASS;                      // created with "new"
$myObj->var->myFunc();                      // Hello World.



■ Polymorphism 多型
若 dericed class 與 parent class 有相同名稱的函數,則 dericed class 會取代 parent class 的函數。

[範例]
class A {
          function F() {
                    print "Error: This method should be re-implemented in the children";
          }
}
class B extends A {
          function F() {
                    print "Polymorphism ....(B)";
          }
}
class C extends A {
          function F() {
                    print "Polymorphism ....(C)";
          }
}
function printTheRightFunc($obj) {
          if ($obj instanceof A) {
                    $obj->F();
          } else {
                    print "Error: Passed wrong kind of object";
          }
          print "<br>";
}
printTheRightSound(new B());              // Polymorphism ....(B)
printTheRightSound(new C());              // Polymorphism ....(C)


■ MAGIC METHODS
Method and function names beginning with a double underscore—such as __construct(),
__destruct(), and __autoload()—are reserved in PHP and are often referred to as magic.

◆ __construct
void __construct ( [mixed args [, ...]] )
Called when a new instance of the class is created.
Parent constructors are not called implicitly if the child class defines a constructor. In order to run a parent constructor, a call to parent::__construct() within the child constructor is required.

[範例]
class BaseClass {
   function __construct() {
       print "In BaseClass constructor";
   }
}
class SubClass extends BaseClass {
   function __construct() {
       parent::__construct();
       print "In SubClass constructor";
   }
}

◆ __destruct
void __destruct ( void )
Called when an instance of the class passes out of memory; this happens when you
either unset() the instance or a script finishes running.

[範例]


◆ __autoload
當使用到 undeclared class 時(如建立物件、使用 static member),會自動呼叫 __autoload 函數。
__autoload 函數會傳入所呼叫的 class 名稱作為參數,可用來作為動態引入外部檔案中的 class 定義來避免發生錯誤。

[範例] 從 MyClass1.php、MyClass2.php 檔案分別載入 MyClass1、MyClass2 類別,省略事先特別指定引入(include、或require)某個檔案動作
function __autoload($class_name) {
      require_once $class_name . '.php';
}
$obj  = new MyClass1();
$obj2 = new MyClass2();


◆ __clone
1. PHP 5 後,傳遞物件時預設行為是使用參考進行傳遞。若需要用到某物件的副本(copy of an object),可使用 __clone() 方法產生副本。
2. 欲製作物件的副本須使用 clone 關鍵字。
3. 物件複製時,可使用自行定義的 __clone() 方法,若使用者未自行定義,則會使用預設的 __clone 方法,預設會拷貝所有的 properties。
4. __clone 函數無法直接呼叫,需使用下列語法複製物件:
 [語法] $replication = clone $src;


[範例]
class MyCar {
      private $gas = 0;
      private $color = "blue";
      function addGas($amount) {
            $this->gas = $this->gas + $amount;
            echo "$amount gallons added to gas tank";
      }
      function __clone() {
            $this->gas = 0;
      }
}
$firstCar = new MyCar;
$firstCar->addGas(10);      // 10 gallons added to gas tank
$secondCar = clone $firstCar;      // $secondCar is blue but contains 0 gallons of gas


◆ __get 和 __set、__isset 和 __unset、__call
void __set ( string property-name, mixed property-value )
mixed __get ( string property-name )
bool __isset ( string property-name )    →PHP 5.1.0
void __unset ( string property-name )    →PHP 5.1.0
mixed __call ( string method-name, array arguments )


1. 藉由 __call,__get 和 __set,__isset 和 __unset 函數可對類別成員進行多載化(overload,重載) 動作
__get() 與 __set() 可取得或設定某物件屬性(property)。
__call() can be used for a variety of purposes.
2. 當存取物件未定義的成員時,會自動呼叫 __call、__get、__set 方法
PHP 中若嘗試存取類別中不存在的屬性時,會自動產生該屬性。但是若類別裡有定義 __set、__get 函數時,則會呼叫 __set、__get 函式進行處理。
若是嘗試呼叫類別中不存在的函式時,會產生「Fatal error: Call to undefined method」的錯誤。 但是若類別裡有定義 __call 函數時,會自動呼叫 __call 函式進行處理。

3. PHP 5+ 所有的 overloading methods 必須宣告為 public,且不能宣告為 static



[範例]
class StrictCoordinateClass {
    private $arr = array('x' => NULL, 'y' => NULL);

    function __get($property) {
        if (array_key_exists($property, $this->arr)) {
              return $this->arr[$property];
        } else {
              print "Error: Can't read a property other than x & y <br>";
        }
    }
    function __set($property, $value) {
        if (array_key_exists($property, $this->arr)) {
              $this->arr[$property] = $value;
        } else {
              print "Error: Can't write a property other than x & y <br>";
        }
    }
} // class StrictCoordinateClass

$myObj = new StrictCoordinateClass();
$myObj->x = 1;
print $myObj->x . "<br>";

$myObj->n = 2;
print $myObj->n;
/* 執行結果
  1
  Error: Can't write a property other than x & y
  Error: Can't read a property other than x & y
  */

[範例]
class MyClass {
      var $x = array(1, 2, 3);

      function __call($m, $a) {
           print "Method $m called:\n";
           var_dump($a);
           return $this->x;
      }
}
$obj = new MyClass();
$a = $obj->test(1, "string here", 5.2, true);
var_dump($a);
/*
Method test called:
array(4) {
   [0]=>
   int(1)
   [1]=>
   string(11) "string here"
   [2]=>
   float(5.2)
   [3]=>
   bool(true)
}
array(3) {
   [0]=>
   int(1)
   [1]=>
   int(2)
   [2]=>
   int(3)
}
*/

[範例]
/* 建立委派模組(delegation model)
    an instance of the class HelloWorldDelegator delegates all method calls to an
    instance of the HelloWorld class
*/
class HelloWorld {
    function display($count) {
        for ($i = 0; $i < $count; $i++) {
            print "Hello, World\n";
        }
        return $count;
    }
}
class HelloWorldDelegator {
    function __construct() {
        $this->obj = new HelloWorld();
    }
    function __call($method, $args) {
        return call_user_func_array(array($this->obj , $method), $args);
    }
    private $obj;
}
$myObj = new HelloWorldDelegator();
print $myObj->display(3);
/* 執行結果
  Hello, World
  Hello, World
  Hello, World
  3
*/


◆ __sleep 和 __wakeup
1. 使用 serialize 函數對物件作序列化時會先自動呼叫 __sleep() 方法,再進行其餘的序列化動作。
    __sleep() 可傳回陣列,該陣列元素為欲進行序列化的變數。
2. 使用 unserialize 函數對物件作反序列化時會先自動呼叫 __wakeup() 函數,再進行其餘的反序列化動作。可用來重建資料庫連線或重新初使化物件(reinitialize the object)。
3. 這 2 個方法無參數值。


[範例]
class Connection {
    protected $link;
    private $server, $username, $password, $db;

    public function __construct($server, $username, $password, $db) {
        $this->server = $server;
        $this->username = $username;
        $this->password = $password;
        $this->db = $db;
        $this->connect();
    }
    private function connect() {
        $this->link = mysql_connect($this->server, $this->username, $this->password);
        mysql_select_db($this->db, $this->link);
    }
    public function __sleep() {
        mysql_close($this->link);
    }
    public function __wakeup() {
        $this->connect();
    }
}


[註]
string serialize ( mixed value )
mixed unserialize ( string str )




◆ __set_state
This static method is called for classes exported by var_export() since PHP 5.1.0.

The only parameter of this method is an array containing exported properties in the form array('property' => value, ...).

http://www.goodphptutorials.com/track/188

◆ __toString
Called when a string representation of the object is required.

1. return the string representation of the object, and when defined, the print command will call it and print the returned string

2. The __toString() method is currently only called by the print and echo language constructs. In the future, they will probably also be called by common string operations, such as string concatenation and explicit casting to string.

[範例]
class MyClass {
   private $myProperty;

   public function __construct($myProperty) {
       $this->myProperty = $myProperty;
   }

   public function __toString() {
       return $this->myProperty;
   }
}
$class = new MyClass('Hello World');
echo $class;      // Hello World,若沒有定義 __toString 函數,會印出 Object id #1



■ Abstract Methods and Classes
abstract class Class-Name {
      ‥‥
}
宣告抽象類別或方法須使用「abstract」關鍵字,抽象類別不能建立實體。
具有抽象方法的類別須宣告為抽象類別,亦即抽象類別須至少包含一個抽象方法。抽象方法只定義方法名稱與參數,不能定義方法的內容,不加大括號「{}」。

[範例]
abstract class Shape {
    function setCenter($x, $y) {
        $this->x = $x;
        $this->y = $y;
    }

    abstract function draw();
    protected $x, $y;
}
class Square extends Shape {
    function draw() {
        // Here goes the code which draws the Square
        ......
    }
}
class Circle extends Shape {
    function draw() {
        // Here goes the code which draws the Circle
        ......
    }
}



■ Interfaces
[定義介面]
interface Interface-Name {
      ‥‥
      function function-name(parameters);
}
[實作介面]
class Class-Name implements Interface-Name1, Interface-Name2, ‥‥ {       
      ‥‥   
}
定義介面須使用「interface」關鍵字,介面內宣告的所有方法都不具有實作部份(只有 function prototypes 無 implementation),介面不能建立實體。
類別實作介面需使用「implements」關鍵字,同一個類別可實作多個介面。實作某介面的類別須定義出該介面所有宣告的方法,或宣告為抽象類別。
介面與實作該介面的類別具有 instanceof (is-a) 的關係。
介面內宣告的方法其 access modifiers 為 public,所以 method prototypes 無法宣告使用其它的 access modifiers。
介面內的屬性須為常數(constants)。

[範例]
interface Loggable {
    function logString();
}
class Person implements Loggable {
    private $name, $address, $idNumber, $age;
    function logString() {
        return "class Person: name = $this->name, ID = $this ->idNumber <br>";
    }
}

[範例]
interface MyInterface {
    public function myFunc1();
    protected function myFunc2($arg);        // Fatal error: Access type for interface method MyInterface::myFunc2() must be omitted or declared public

    var $var1;        //Fatal error: Interfaces may not include member variables
    const CVAR1;                // Parse error: parse error, unexpected ';', expecting '='
    const CVAR2 = "COCSTANT.....";        // OK
}


[範例]
interface MyA {
   function a(MyA $object);
}
interface MyB {
   function b(MyB $object);
}
class MyC implements MyA, MyB {
   function a(MyA $object) {
         // ...
   }
   function b(MyB $object) {
        // ...
   }
}
$a = new MyC;
$b = new MyC;
$a->a($b);
$a->b($b);
/*
function Func1(ClassName $object) {
      ......
}
可改寫成如下
function Func1($object) {
      if (!($object instanceof ClassName)) {
            die("Argument must be an instance of ClassName");
      }
          ......
}
*/




■ Inheritance of Interfaces
介面可繼承其他介面,並允許介面的多重繼承。

1. Interfaces may inherit from other interfaces. The syntax is similar to that of classes, but allows multiple inheritance:
2. an interface can only extend other interfaces if they don't clash with each other (which means that you receive an error if I2 defines methods or constants already defined by I1).

[範例]
interface I1 extends I2, I3, ... {
    ...
}





■ Exceptions 例外處理
◆ throw
throw object;
丟出例外

◆ try...catch

[說明]
1. try 敘述之後至少必須有一個 catch 敘述。
2. catch 區塊內可再丟出(rethrow) 例外
Multiple catch blocks can be used to catch different classes of exeptions.
Normal execution (when no exception is thrown within the try block, or when a catch matching the thrown exception's class is not present) will continue after that last catch block defined in sequence.
Exceptions can be thrown (or re-thrown) within a catch block.

When an exception is thrown, code following the statement will not be executed, and PHP will attempt to find the first matching catch block.
If an exception is not caught, a PHP Fatal Error will be issued with an "Uncaught Exception ..." message, unless a handler has been defined with set_exception_handler().
Up to version 4, developers had to use the 'set_error_handler' callback function to implement some sort of generic error handling.

PHP5 無 finally 區塊處理
# Checked Exceptions vs Unchecked Exceptions
You have to handle all exceptions, otherwise PHP5 will throw an Unchecked Exception Error. You have to handle it, but you don't have to do anything with it (ie leave empty catch block, use generic exception)

[範例]
try {
    ......         // Code which might throw an exception
} catch (FirstExceptionClass $exception) {
    ......         // Code which handles this exception
} catch (SecondExceptionClass $exception) {
}

[範例]
try {
    $error_msg = '丟出錯誤';
    throw new Exception($error_msg);
    echo 'Never executed';        // Code following an exception is not executed
} catch (Exception $e) {
    echo 'Exception Caughted: ',  $e->getMessage(), "<br>";
}
echo 'Hello World!';        // Continue execution
/*
Exception Caughted: 丟出錯誤
Hello World!
*/

◆ Extending Exceptions
PHP5 predefines the Exception class that has useful features suitable for exception reporting

A User defined Exception class can be defined by extending the built-in Exception class.

Built in Exception class
class Exception {
   protected $message = 'Unknown exception';  // exception message
   protected $code = 0;                        // user defined exception code
   protected $file;                            // source filename of exception
   protected $line;                            // source line of exception

   function __construct($message = null, $code = 0);

   final function getMessage();                // message of exception
   final function getCode();                  // code of exception
   final function getFile();                  // source filename
   final function getLine();                  // source line
   final function getTrace();                  // an array of the backtrace()
   final function getTraceAsString();          // formated string of trace

   /* Overrideable */
   function __toString();                      // formated string for display
}

If a class extends the built-in Exception class and re-defines the constructor, it is highly recomended that it also call parent::__construct() to ensure all available data has been properly assigned.
The __toString() method can be overriden to provide a custom output when the object is presented as a string.

[範例]
class MyException extends Exception {
     function __construct($exception) {
           $this->exception = $exception;
     }
     function Display() {
           print "MyException: $this->exception\n";
     }
}
try {
      throw new MyException('Hello World');
} catch (MyException $exception) {
      $exception->Display();
} catch (Exception $exception) {
      echo $exception;
}
/*
   MyException: Hello World
*/

from http://bbs.wefong.com/viewthread.php?tid=1594633&extra=page%3D1
Free Web Hosting