* 本文是對《Classes and Objects in PHP5》系列文章的補充和修正,介紹了PHP5對象體系的總體框架,但有些特性沒有具體介紹。強烈建議在讀過《Classes and Objects in PHP5》后閱讀本文。
PHP5推出的對象體系相信是大家最為期待的。PHP5借鑒了Java2的對象模型,提供了較為強大的面向?qū)ο缶幊讨С郑褂肞HP來實現(xiàn)OO將變得輕松和自然。
對象傳遞
PHP5使用了Zend引擎II,對象被儲存于獨立的結(jié)構(gòu)Object Store中,而不像其它一般變量那樣儲存于Zval中(在PHP4中對象和一般變量一樣存儲于Zval)。在Zval中僅存儲對象的指針而不是內(nèi)容(value)。當我們復制一個對象或者將一個對象當作參數(shù)傳遞給一個函數(shù)時,我們不需要復制數(shù)據(jù)。僅僅保持相同的對象指針并由另一個zval通知現(xiàn)在這個特定的對象指向的Object Store。由于對象本身位于Object Store,我們對它所作的任何改變將影響到所有持有該對象指針的zval結(jié)構(gòu)----表現(xiàn)在程序中就是目標對象的任何改變都會影響到源對象。.這使PHP對象看起來就像總是通過引用(reference)來傳遞,因此PHP中對象默認為通過“引用”傳遞,你不再需要像在PHP4中那樣使用&來聲明。
垃圾回收機制
某些語言,最典型的如C,需要你顯式地要求分配內(nèi)存當你創(chuàng)建數(shù)據(jù)結(jié)構(gòu)。一旦你分配到內(nèi)存,就可以在變量中存儲信息。同時你也需要在結(jié)束使用變量時釋放內(nèi)存,這使機器可以空出內(nèi)存給其它變量,避免耗光內(nèi)存。
PHP可以自動進行內(nèi)存管理,清除不再需要的對象。PHP使用了引用計數(shù)(reference counting)這種單純的垃圾回收(garbage collection)機制。每個對象都內(nèi)含一個引用計數(shù)器,每個reference連接到對象,計數(shù)器加1。當reference離開生存空間或被設為NULL,計數(shù)器減1。當某個對象的引用計數(shù)器為零時,PHP知道你將不再需要使用這個對象,釋放其所占的內(nèi)存空間。
例如:
<?php class Person{ } function sendEmailTo(){ }
$haohappy = new Person( ); // 建立一個新對象: 引用計數(shù) Reference count = 1 $haohappy2 = $haohappy; // 通過引用復制: Reference count = 2 unset($haohappy); // 刪除一個引用: Reference count = 1 sendEmailTo($haohappy2); // 通過引用傳遞對象: // 在函數(shù)執(zhí)行期間: // Reference count = 2 // 執(zhí)行結(jié)束后: // Reference count = 1
unset($haohappy2); // 刪除引用: Reference count = 0 自動釋放內(nèi)存空間
?>
以上是PHP5在內(nèi)存管理上的變化,也許大家不怎么感興趣。下面我們來看看PHP5中的對象模型和PHP4有什么具體的不同之處:
★ 新增功能
★ 改進功能
1) ★ Private and Protected Members 私有和保護類成員(屬性,方法)
2) ★ Abstract Classes and Methods 抽象類和抽象方法
3) ★ Interfaces 接口
4) ★ Class Type Hints 類型指示 =
5) ★ final final關鍵字 =
6) ★ Objects Cloning 對象復制 =
7) ★ Constructors and Destructors 構(gòu)造函數(shù)和析構(gòu)函數(shù)
8) ★ Class Constants 類常量 =
9) ★ Exceptions 異常處理
10) ★ Static member 靜態(tài)類成員
11) ★__METHOD__ constant __METHOD__常量 =
12) ★ Reflection 反射機制
第1、2、3、7、10請自行查閱本文末尾的《Classes and Objects in PHP5》系列,其中已有詳細介紹,本文中不再講解。第9點異常處理和第12點反射機制內(nèi)容較為豐富,限于篇幅亦不在文中介紹,請關注即將推出的《PHP & More》電子雜志第二期,會專門撰文介紹。
以下向大家介紹第4、5、6、8、11點語言特性:
4) ★ Class Type Hints 類型指示
大家都知道,PHP是一種弱類型的語言。在使用變量前不需要定義,不需要聲明變量的數(shù)據(jù)類型。這在編程中帶來很多便利,但也帶了一些隱患,特別當變量的類型變化時。在PHP5增加了類型指示,可以在執(zhí)行過程中自動對類方法的參數(shù)類型進行判斷。這類似于Java2中的RTTI,配合reflection可以讓我們很好地控制對象。
<?php interface Foo { function a(Foo $foo); }
interface Bar { function b(Bar $bar); }
class FooBar implements Foo, Bar { function a(Foo $foo) { // ... }
function b(Bar $bar) { // ... } }
$a = new FooBar; $b = new FooBar;
$a->a($b); $a->b($b); ?>
在強類型語言中,所有變量的類型將在編譯時進行檢查,而在PHP中使用類型指示來對類型的檢查則發(fā)生在運行時。如果類方法參數(shù)的類型不對,將會報出類似“Fatal error: Argument 1 must implement interface Bar…”這樣的錯誤信息。
以下代碼:
<?php function foo(ClassName $object) { // ... } ?>
相當于:
<?php function foo($object) { if (!($object instanceof ClassName)) { die("Argument 1 must be an instance of ClassName"); } } ?>
5) ★ final final關鍵字
PHP5中新增加了final關鍵字,它可以加在類或類方法前。標識為final的類方法,在子類中不能被覆寫。標識為final的類,不能被繼承,而且其中的方法都默認為final類型。
Final方法:
<?php class Foo { final function bar() { // ... } } ?>
Final類:
<?php final class Foo { // class definition }
// 下面這一行是錯誤的 // class Bork extends Foo {} ?>
6) ★ Objects Cloning 對象復制
前面在內(nèi)存管理部份說過,PHP5中默認通過引用傳遞對象。像使用$object2=$object1這樣的方法復制出的對象是相互關聯(lián)的。如果我們確實需要復制出一個值與原來相同的對象而希望目標對象與源對象沒有關聯(lián)(像普通變量那樣通過值來傳遞),那么就需要使用clone關鍵字。如果還希望在復制的同時變動源對象中的某些部份,可以在類中定一個__clone()函數(shù),加入操作。
<?php //對象復制 class MyCloneable { static $id = 0;
function MyCloneable() { $this->id = self::$id++; }
/* function __clone() { $this->address = "New York"; $this->id = self::$id++; } */ }
$obj = new MyCloneable();
$obj->name = "Hello"; $obj->address = "Tel-Aviv";
print $obj->id . "\n";
$obj_cloned = clone $obj;
print $obj_cloned->id . "\n"; print $obj_cloned->name . "\n"; print $obj_cloned->address . "\n"; ?>
以上代碼復制出一個完全相同的對象。
然后請把function __clone()這一個函數(shù)的注釋去掉,重新運行程序。則會復制出一個基本相同,但部份屬性變動的對象。
8) ★ Class Constants 類常量
PHP5中可以使用const關鍵字來定義類常量。
<?php class Foo { const constant = "constant"; }
echo "Foo::constant = " . Foo::constant . "\n"; ?>
11) ★__METHOD__ constant __METHOD__常量
__METHOD__ 是PHP5中新增的“魔術”常量,表示類方法的名稱。 魔術常量是一種PHP預定義常量,它的值可以是變化的,PHP中的其它已經(jīng)存在的魔術常量有__LINE__、__FILE__、__FUNCTION__、__CLASS__等。
<?php class Foo { function show() { echo __METHOD__; } }
class Bar extends Foo { }
Foo::show(); // outputs Foo::show Bar::show(); // outputs Foo::show either since __METHOD__ is // compile-time evaluated token
function test() { echo __METHOD__; }
test(); // outputs test ?> (出處:Viphot)
|