PHP5/ZendEngine2的改進_PHP

來源:互聯網
上載者:User
關鍵字 改進 方法 print 對象 function 一個 定義
新的物件模型
PHP中的對象處理部分已完全重寫,具有更佳的效能和更多的功能。在先前的PHP版本中,對象被當做原始的簡單類型
(如integer和string)來處理,這種方法的缺點是當變數被賦值或作為參數傳遞時,得到的是對象拷貝。而在新版本中,
對象是通過控制代碼來引用的,而不是通過對象的值(控制代碼想象為對象的標識符)。
很多PHP程式員可能未意識到老的物件模型的“copying quirks“,因此以前的大多數PHP程式將不需要做任何更改
即可運行,或只做很少的改動。

私人和保護成員
PHP 5引進了私人和保護成員變數,它們可以定義可視化的類屬性。
樣本
保護成員變數能在該類的子類中被訪問,而私人成員變數只能在所屬類中被訪問。
private $Hello = "Hello, World!\n";
protected $Bar = "Hello, Foo!\n";
protected $Foo = "Hello, Bar!\n";
function printHello() {
print "MyClass::printHello() " . $this->Hello;
print "MyClass::printHello() " . $this->Bar;
print "MyClass::printHello() " . $this->Foo;
}
}
class MyClass2 extends MyClass {
protected $Foo;
function printHello() {
MyClass::printHello(); /* Should print */
print "MyClass2::printHello() " . $this->Hello; /* Shouldn't print out anything */
print "MyClass2::printHello() " . $this->Bar; /* Shouldn't print (not declared)*/
print "MyClass2::printHello() " . $this->Foo; /* Should print */
}
}
$obj = new MyClass();
print $obj->Hello; /* 不輸出任何內容,以下類同 */
print $obj->Bar; /* Shouldn't print out anything */
print $obj->Foo; /* Shouldn't print out anything */
$obj->printHello(); /* Should print */
$obj = new MyClass2();
print $obj->Hello; /* Shouldn't print out anything */
print $obj->Bar; /* Shouldn't print out anything */
print $obj->Foo; /* Shouldn't print out anything */
$obj->printHello();
?>

私人和保護方法

PHP 5(ZEND引擎2)中,私人方法和保護方法也被引入。
樣本:
private function aPrivateMethod() {
echo "Foo::aPrivateMethod() called.\n";
}
protected function aProtectedMethod() {
echo "Foo::aProtectedMethod() called.\n";
$this->aPrivateMethod();
}
}
class Bar extends Foo {
public function aPublicMethod() {
echo "Bar::aPublicMethod() called.\n";
$this->aProtectedMethod();
}
}
$o = new Bar;
$o->aPublicMethod();
?>
以前代碼中的使用者自訂類或方法中雖然沒有定義"public," "protected" 或 "private"等關鍵字,但無需修改即可運行。

抽象類別和方法
PHP 5還引入了抽象類別和方法。抽象方法只聲明方法的”符號”,而不提供它的實現。一個包含抽象方法的類需要聲明為”abstract”。
例如:
phpabstract class AbstractClass {
abstract public function test();
}
class ImplementedClass extends AbstractClass {
public function test() {
echo "ImplementedClass::test() called.\n";
}
}
$o = new ImplementedClass;$o->test();
?>
抽象類別不能執行個體化。
舊的代碼中的使用者自訂類或方法中雖未定義"abstract”關鍵字,但無需修改就可以運行。
介面(Interfaces)
ZEND引擎2.0引入了介面。一個類可以實現任意的介面列表。
例如:

舊的代碼中的使用者定義類或方法中雖然沒有定義"interface”關鍵字,但無需修改就可以正常運行。

類類型提示(Class Type Hints)
在保留類無需定義類型的同時,PHP 5引入了類類型提示來聲明,以期望把對象的類通過參數傳遞給一個方法。
例如:
a($b);$a->b($b);?>
這些類類型提示不是象一些需要類型定義的語言那樣在編譯中進行檢查,而是在運行時進行檢查。這就意味著:

is equivalent to:

這種文法只用於對象或類,不適用於內建(built-in)類型。

Final關鍵字(final)
PHP 5引入了“final”關鍵字以定義在子類中不能被覆蓋的成員或方法。
例:
class Foo { final function bar() { // ... }}?>
以前所寫代碼中的使用者自訂類或方法中雖未定義"final"關鍵字,但無需修改就可以運行了。
對象複製(Object Cloning)
PHP 4在對象被複製時,使用者不能判斷運行那個拷貝建構函式。在複製時,PHP 4根據對象的屬性
一位一位地複製一個同樣的複製品。
每次都要建立一個完全一樣的複製品並不總是我們想要的。一個很好的複製構造例子是,當有
一個代表一個GTK視窗的對象,它擁有該視窗的所有資源,當你建立一個拷貝時,你可能需要一
個新的視窗,它擁有原視窗的所有屬性,但需要擁有新視窗的資源。另外一個例子是你有一個
對象引用了另外一個對象,當你複製父物件時,你希望建立那個引用對象的新執行個體,以使複製品有一個單獨的拷貝。
對一個對象的拷貝通過調用對象的__clone()方法完成:
$copy_of_object = $object->__clone();
?>

當開發人員請求建立一個對象的新的拷貝時,ZEND引擎會檢查是否已經定義了__clone()方法。如果未定義
的話,它會調用一個預設的__clone()方法來複製該對象的所有屬性。如果定義了該方法,該方法會負責
在拷貝中設定必要的屬性。為使用方便,引擎會提供一個函數從來源物件中匯入所有的屬性,這樣它就可
以先得到一個具有值的來源物件拷貝,然後只需要對需要改變的屬性進行覆蓋即可。
例:
class MyCloneable {
static $id = 0;

function MyCloneable() {
$this->id = self::$id++;
}

function __clone() {
$this->name = $that->name;
$this->address = "New York";
$this->id = self::$id++;
}
}

$obj = new MyCloneable();

$obj->name = "Hello";
$obj->address = "Tel-Aviv";

print $obj->id . "\n";

$obj = $obj->__clone();

print $obj->id . "\n";
print $obj->name . "\n";
print $obj->address . "\n";
?>

統一的構造方法
ZEND引擎允許開發人員定義類的構造方法。具有構造方法的類在建立時會首先調用構造方法,構造
方法適用於在正式使用該類前進行的初始化。
在PHP4中,構造方法的名稱與類名相同。由於在衍生類別中調用父類的作法比較普遍,因此導致在
PHP4中當類在一個大型的類繼承中進行移動時,處理方式有點笨拙。當一個衍生類別被移動到一個不同
的父類中時,父類的構造方法名必然是不同的,這樣的話衍生類別中的有關調用父類構造方法的語句需要改寫。
PHP5引入了一個定義構造方法的標準方式,通過調用它們的__construct()來定義。
樣本:
class BaseClass {
function __construct() {
print "In BaseClass constructor\n";
}
}

class SubClass extends BaseClass {
function __construct() {
parent::__construct();
print "In SubClass constructor\n";
}
}

$obj = new BaseClass();
$obj = new SubClass();
?>

為向後相容,當PHP5類不能找到__construct()方法時,會通過老的方法也就是類名
來尋找構造方法。這意味著唯一可能產生相容性問題的是在以前的代碼中已經使用了
一個名為__construct()的方法名。

析構方法
定義析構方法是十分有用的。析構方法可以記錄調試資訊,關閉資料庫連接,還有做其它的掃尾
工作。PHP4中並無此機制,儘管PHP已支援註冊在請求結束時需要啟動並執行函數。
PHP5引入了與其它物件導向語言如Java語言相似的析構方法:當最後一個該對象的引用被清除時,
系統將會在該對象從記憶體中釋放前調用名為__destruct()的析構方法。
樣本:
class MyDestructableClass {
function __construct() {
print "In constructor\n";
$this->name = "MyDestructableClass";
}

function __destruct() {
print "Destroying " . $this->name . "\n";
}
}

$obj = new MyDestructableClass();
?>

和構造方法相似,引擎將不調用父類的析構方法,為調用該方法,你需要在子
類的析構方法中通過parent::__destruct()語句進行調用。

常量
PHP 5 引入了類常量(per-class constants)定義:
class Foo {
const constant = "constant";
}

echo "Foo::constant = " . Foo::constant . "\n";
?>
PHP5允許常量中包含運算式,但在編譯時間常量中的運算式將被計算,
因此常量不能在運行中改變它的值。
class Bar {
const a = 1<<0;
const b = 1<<1;
const c = a | b;
}
?>
以前代碼中的使用者自訂類或方法中雖然未定義"const”關鍵字,
但無需修改就可以運行。

異常(Exceptions)
PHP4中沒異常處理,PHP5引入了與其它與語言相似的異常處理模型。
class MyExceptionFoo extends Exception {
function __construct($exception) {
parent::__construct($exception);
}
}

try {
throw new MyExceptionFoo("Hello");
} catch (MyExceptionFoo $exception) {
print $exception->getMessage();
}
?>

以前代碼中的使用者自訂類或方法中雖未定義'catch', 'throw' 和 'try'關鍵字,但無需修改
就可以運行。

函數返回對象值
在PHP4中,函數不可能返回對象的值並對返回的對象進行方法調用,隨著Zend Engine 2
(ZEND引擎2)的出現,以下調用成為可能:
class Circle {
function draw() {
print "Circle\n";
}
}

class Square {
function draw() {
print "Square\n";
}
}

function ShapeFactoryMethod($shape) {
switch ($shape) {
case "Circle":
return new Circle();
case "Square":
return new Square();
}
}

ShapeFactoryMethod("Circle")->draw();
ShapeFactoryMethod("Square")->draw();
?>

靜態類中的靜態成員變數可初始化
例如:
class foo {
static $my_static = 5;
}

print foo::$my_static;
?>


靜態方法(Static Methods)
PHP5引入了關鍵字'static'來定義一個靜態方法,這樣可以從對象外進行調用。
例如:

class Foo {
public static function aStaticMethod() {
// ...
}
}

Foo::aStaticMethod();
?>

虛擬變數$this在被定義為靜態(static)的方法中無效。


Instanceof

PHP5引入了 “instanceof“關鍵字來確定一個對象是否是某一個對象的執行個體,或某一個對象的派生,或使用了某一個介面。

樣本:

class baseClass { }

$a = new baseClass;

if ($a instanceof basicClass) {
echo "Hello World";
}
?>



靜態函數變數(Static function variables)
所有的靜態變數現在在編譯時間進行處理,這允許開發人員通過引用來指定靜態變數。這個變化提高了效率但意味著不可能對靜態變數進行間接引用。


函數中通過引用方式傳遞的參數允許有預設值
例如:

function my_function(&$var = null) {
if ($var === null) {
die("$var needs to have a value");
}
}
?>


__autoload()


在初始化一個未定義的類時,__autoload()攔截函數(interceptor function)將被自動調
用。類名將作為__autoload()攔截函數唯一參數傳遞給它。
例如:
function __autoload($className) {
include_once $className . ".php";
}

$object = new ClassName;
?>


方法和屬性調用的重載
所有方法調用和屬性訪問都可以通用 __call(), __get() 和 __set()方法來重載。

例: __get() 和 __set()
class Setter {
public $n;
public $x = array("a" => 1, "b" => 2, "c" => 3);

function __get($nm) {
print "Getting [$nm]\n";

if (isset($this->x[$nm])) {
$r = $this->x[$nm];
print "Returning: $r\n";
return $r;
} else {
print "Nothing!\n";
}
}

function __set($nm, $val) {
print "Setting [$nm] to $val\n";

if (isset($this->x[$nm])) {
$this->x[$nm] = $val;
print "OK!\n";
} else {
print "Not OK!\n";
}
}
}

$foo = new Setter();
$foo->n = 1;
$foo->a = 100;
$foo->a++;
$foo->z++;
var_dump($foo);
?>



樣本: __call()

class Caller {
var $x = array(1, 2, 3);

function __call($m, $a) {
print "Method $m called:\n";
var_dump($a);
return $this->x;
}
}

$foo = new Caller();
$a = $foo->test(1, "2", 3.4, true);
var_dump($a);
?>
  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.