程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> PHP面向對象中的重要知識點(二)

PHP面向對象中的重要知識點(二)

編輯:關於PHP編程

1. __toString:       當對象被打印時,如果該類定義了該方法,則打印該方法的返回值,否則將按照PHP的缺省行為輸出打印結果。該方法類似於Java中的toString()。   復制代碼 <?php class TestClass {     public function __toString() {         return "This is TestClass::__toString.\n";     } }   $testObj = new TestClass(); print $testObj; 復制代碼     運行結果如下:   Stephens-Air:Desktop$ php Test.php  This is TestClass::__toString. 2. __get和__set:       這兩個方法用於處理類中未聲明的屬性訪問。當對象使用者試圖訪問未聲明的對象屬性時,__get()會被調用,並帶有一個包含要訪問的屬性名稱字符串作為參數。無論從__get()方法返回什麼,都會直接返回給調用者,就如同帶有該值的屬性存在一樣。另外需要注意的是,如果屬性存在,但是其訪問可見性為private或protected,那麼這兩個攔截方法同樣會被調用,反之,如果屬性存在切可訪問,那麼直接訪問屬性即可,這兩個方法將不再會被調用。以下為__get()攔截方法的示例代碼:   復制代碼 <?php class TestClass {     private $privateField;     public $publicField;     public function __construct() {         $this->privateField = "This is a private Field.\n";         $this->publicField = "This is a public Field.\n";     }       public function __get($property) {         print "__get() is called.\n";         $method = "get${property}";         if (method_exists($this, $method)) {             return $this->$method();         }         return "This is undefined field.\n";     }     public function getPrivateField() {         return $this->privateField;     } }   $testObj = new TestClass(); print $testObj->privateField; print $testObj->undefinedField; print $testObj->publicField; 復制代碼     運行結果如下:   Stephens-Air:Desktop$ php Test.php  __get() is called. This is a private Field. __get() is called. This is undefined field. This is a public Field.     __set()方法被調用的規則和__get()基本相同,差別是用於攔截未定義或不可見類屬性的賦值操作。另外,該方法接收兩個參數,分別是屬性名稱和要設定的值。見如下代碼示例:   復制代碼 <?php class TestClass {     private $privateField;     public $publicField;     public function __construct() {         $this->privateField = "This is a private Field.\n";         $this->publicField = "This is a public Field.\n";     }     public function __get($property) {         print "__get() is called.\n";         $method = "get${property}";         if (method_exists($this, $method)) {             return $this->$method();         }         return "This is an undefined field.\n";     }     public function __set($property, $value) {         print "__set is called.\n";         $method = "set${property}";         if (method_exists($this, $method)) {             $this->$method($value);         } else {             print "This is an undefined field.\n";         }     }     public function getPrivateField() {         return $this->privateField;     }     public function setPrivateField($value) {         $this->privateField = $value;     } }   $testObj = new TestClass(); $testObj->privateField = "This is a private Field after set.\n"; $testObj->undefinedField = "This is a undefined Field after set.\n"; $testObj->publicField = "This is a public Field after set.\n";   print $testObj->privateField; print $testObj->undefinedField; print $testObj->publicField; 復制代碼     運行結果如下:   復制代碼 Stephens-Air:Desktop$ php Test.php  __set is called. __set is called. This is an undefined field. __get() is called. This is a private Field after set. __get() is called. This is an undefined field. This is a public Field after set. 復制代碼 3. __isset和__unset:       這兩個攔截方法被調用的規則和__get()和__set()非常類似,只是用於類中不存在或不可見屬性被isset()和unset()兩個全局方法應用時才會被分別觸發。    復制代碼 <?php class TestClass {     private $privateField;     public $publicField;     public function __construct() {         $this->privateField = "Defined private field";         $this->publicField = "Defined public field";     }     public function __isset($property) {         print "__isset is called.\n";         return isset($this->$property);     }     public function __unset($property) {         print "__unset is called.\n";         if (isset($this->$property)) {             unset($this->$property);         }     } }   $testObj = new TestClass(); print 'isset($testObj->privateField) is '.(isset($testObj->privateField) ? "true" : "false")."\n"; print 'isset($testObj->undefinedField) is '.(isset($testObj->undefinedField) ? "true" : "false")."\n"; print 'isset($testObj->publicField) is '.(isset($testObj->publicField) ? "true" : "false")."\n";   print "After unset......\n"; //下面兩個函數調用後,$testObj的兩個對象屬性均會變為不可用。 //另外從輸出結果來看,__unset方法僅僅被調用一次,因為publicField為可見屬性,所以__unset不會因該屬性而被調用。 unset($testObj->privateField); unset($testObj->publicField);   print 'isset($testObj->privateField) is '.(isset($testObj->privateField) ? "true" : "false")."\n"; print 'isset($testObj->publicField) is '.(isset($testObj->publicField) ? "true" : "false")."\n"; 復制代碼     運行結果如下:   復制代碼 Stephens-Air:Desktop$ php Test.php  __isset is called. isset($testObj->privateField) is true __isset is called. isset($testObj->undefinedField) is false isset($testObj->publicField) is true After unset...... __unset is called. __isset is called. isset($testObj->privateField) is false __isset is called. isset($testObj->publicField) is false 復制代碼 4. __call:       __call()方法是一個非常有用但又非常容易被濫用的攔截方法。當對象使用者試圖訪問當前對象未定義的成員函數時,__call()會被自動調用,同時傳遞兩個參數,分別為函數名稱和傳遞給調用函數的所有參數(數組)。__call方法返回的任何值都會返回給函數調用者,就如同該成員函數真實存在一樣。下面給出一個非常有用的委托示例。    復制代碼 <?php class DelegateClass {     function printMessage($arg1, $arg2) {         print "DelegateClass:delegatedMethod is called.\n";         print '$arg1 = '.$arg1.'and $arg2 = '.$arg2."\n";     } } class TestClass {     private $delegateObj;     public function __construct() {         $this->delegateObj = new DelegateClass();     }     public function __call($method, $args) {         $this->delegateObj->$method($args[0],$args[1]);     } }   $testObj = new TestClass(); $testObj->printMessage("hello","world"); 復制代碼     運行結果如下:   Stephens-Air:Desktop$ php Test.php  DelegateClass:delegatedMethod is called. $arg1 = helloand $arg2 = world     從以上示例可以看出,TestClass並未聲明printMessage成員方法,但是通過__call()方法的巧妙橋接直接傳遞給了委托對象。個人認為該技巧為雙刃劍,切勿過度使用。   5. 回調函數:        回調函數的應用場景無須多述,在C/C++中充斥著無數的回調函數典型用例。 這裡只是簡單給出PHP中回調函數的使用規則。見如下示例代碼和關鍵性注釋:    復制代碼 <?php class Product {     public $name;     public $price;     public function __construct($name, $price) {         $this->name = $name;         $this->price = $price;     } }   class ProcessSale {     private $callbacks;     function registerCallback($cb) {         if (!is_callable($cb)) {             throw new Exception("callback not callable.");         }         $this->callbacks[] = $cb;     }     function sale($product) {         print "{$product->name}: processing \n";         foreach ($this->callbacks as $cb) {             //以下兩種調用方式均可。             call_user_func($cb, $product);             $cb($product);         }     } }   $logger = function($product) {     print "    logging ({$product->name})\n"; };   $processor = new ProcessSale(); $processor->registerCallback($logger); $processor->sale(new Product("shoes",6)); print "\n"; $processor->sale(new Product("coffee",6)); 復制代碼     運行結果如下:   復制代碼 Stephens-Air:Desktop$ php Test.php  shoes: processing      logging (shoes)     logging (shoes)   coffee: processing      logging (coffee)     logging (coffee) 復制代碼 6. use(閉包):       在Javascript中存在大量的閉包應用,PHP中的閉包則是通過use關鍵字來完成的。對於閉包這個概念本身而言,簡要的說就是函數內的代碼可以訪問其父作用域中的變量。見如下示例代碼和關鍵性注釋:   復制代碼 <?php class Product {     public $name;     public $price;     public function __construct($name, $price) {         $this->name = $name;         $this->price = $price;     } }   class ProcessSale {     private $callbacks;     function registerCallback($cb) {         if (!is_callable($cb)) {             throw new Exception("callback not callable.");         }         $this->callbacks[] = $cb;     }     function sale($product) {         print "{$product->name}: processing \n";         foreach ($this->callbacks as $cb) {             $cb($product);         }     } }   class Totalizer {     static function warnAmount($amt) {         $count = 0;         //注意這裡的$amt和$count均為閉包變量,其中&$count是以引用的形式傳遞的,即一旦函數內部修改了該變量的值,         //那麼下次再訪問該閉包變量時,$count將為之前調用中修改後的值。         return function($product) use($amt, &$count) {             $count += $product->price;             print "     count: $count\n";             if ($count > $amt) {                 print "     high price reached: {$count}\n";             }         };     } }   $processor = new ProcessSale(); $processor->registerCallback(Totalizer::warnAmount(8)); $processor->sale(new Product("shoes",6)); $processor->sale(new Product("coffee",6)); 復制代碼     運行結果如下:   shoes: processing       count: 6 coffee: processing       count: 12      high price reached: 12 注:該Blog中記錄的知識點,是在我學習PHP的過程中,遇到的一些PHP和其他面向對象語言相比比較獨特的地方,或者是對我本人而言確實需要簿記下來以備後查的知識點。雖然談不上什麼深度,但是還是希望能與大家分享。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved