- 論壇徽章:
- 0
|
盡管開發(fā)和運(yùn)行環(huán)境早已經(jīng)是php5了,但是一直沒有使用php5的OO特性寫代碼,F(xiàn)在終于有機(jī)會拿著研究C++ OOP的精神,研究PHP5的OO特性。本文設(shè)計到一些細(xì)節(jié),有些代碼僅僅為了測試,有意為之,不要見笑。
(研究的是不是有點(diǎn)晚了,php6都要出來啦^_^)
從PHP手冊中看到這樣一句話,一開始有些不理解。
于是做了這樣的例子:
<?php
class ClassB{
const NAME = "Class B";
public $a = ClassB::NAME;
public function foo(){
echo $this->a.":: foo call\n";
echo "'this' is a {$this->a} object\n";
}
};
class ClassA{
const NAME = "class A";
public $a = ClassA::NAME;
public function createB(){
return new ClassB();
}
public function foo(){
echo $this->a.":: foo call\n";
echo "\n\nCall a object function\n";
$this->createB()->foo();
echo "\n\n function called statically \n";
ClassB::foo();
}
}
$A = new ClassA();
$A->foo();
?>
|
發(fā)現(xiàn)在ClassA里面直接以ClassB::foo();的形式“靜態(tài)調(diào)用”,ClassB::foo();里面的this的確是對象$A的引用。
注意是“靜態(tài)調(diào)用(called statically)”而非靜態(tài)方法。經(jīng)過測試,靜態(tài)方法內(nèi)不允許this偽變量。
上面的特性-- 在方法被靜態(tài)調(diào)用的上下文環(huán)境中,this是調(diào)用者的引用,這個特性可以應(yīng)用到多級繼承時,提供子類訪問基類的途徑:
<?php
class BaseClass
{
// Redefine the parent method
public final $abc = "Base";
function displayVar()
{
echo "this->abc:".$this->abc."\n";
echo "Base class\n";
parent::displayVar();
}
}
class SimpleClass extends BaseClass
{
public $abc = "SimpleClass";
// Redefine the parent method
function displayVar()
{
echo "this->abc:".$this->abc."\n";
echo "SimpleClass class\n";
}
}
class ExtendClass extends SimpleClass
{
public $abc = "ExtendClass";
// Redefine the parent method
function displayVar()
{
echo "this->abc:".$this->abc."\n";
echo "Extending class\n";
parent::displayVar();
BaseClass::displayVar();
}
}
$extended = new ExtendClass();
$extended->displayVar();
?>
輸出:
./test_extends.php
this->abc:ExtendClass
Extending class
this->abc:ExtendClass
SimpleClass class
this->abc:ExtendClass
Base class
|
PHP的__construct不是太嚴(yán)格,甚至允許$obj->__construct , 當(dāng)然這也可能是為了兼容以前的代碼。
但是下面的測試很意外,ClassA::__construct()的調(diào)用引起php croe dump了。
<?php
class ClassAAA{
function __construct()
{
echo "ClassA::__construct\n";
}
};
ClassAAA::__construct();
?>
| 我的php版本:
php -v
PHP 5.2.1 (cli) (built: Apr 28 2007 15:27:26)
Copyright (c) 1997-2007 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies
[2007-09-29更新]:
php 5.2.4已經(jīng)更正了這個bug,現(xiàn)在運(yùn)行ClassAAA::__construct();會得到一個嚴(yán)重錯誤:
Fatal error: Non-static method ClassAAA::__construct() cannot be called statically in /usr/home/duzhigang/php5/test_construct.php on line 10
從手冊看到一句話:
這是因?yàn)閷ο蟮奈鰳?gòu)時機(jī)依賴php的實(shí)際實(shí)現(xiàn),可能在php銷毀對象的時候,代碼塊已經(jīng)不在我們的try catch控制中了。
對于我下面測試的這個版本,php在一個對象的引用計數(shù)為0時,立即調(diào)用析構(gòu)函數(shù)進(jìn)行銷毀,所以有幸能捕獲到析構(gòu)函數(shù)內(nèi)的異常。
但是手冊里面的這個“注意”是對的,因?yàn)?/font>php沒有明確定義析構(gòu)函數(shù)執(zhí)行的時機(jī),所以我們不應(yīng)該在析構(gòu)函數(shù)中拋出異常。
<?php
class MyDestructableClass {
function __construct() {
print "In constructor\n";
$this->name = "MyDestructableClass";
}
function __destruct() {
print "Destroying " . $this->name . "\n";
throw new Exception("my error");
}
}
function abc(){
try{
try{
$obj = new MyDestructableClass();
//return $obj;
}
catch(Exception $e){
echo "abc::".$e->getMessage();
}
}
catch(Exception $e){echo "abc::".$e->getMessage();}
//echo("abc fun run\n");
}
try{
abc();
}
catch(Exception $e){
echo "main::".$e->getMessage();
}
try{
unset($r);
}
catch(Exception $e){
echo "main 2::".$e->getMessage();
}
?>
|
【未完待續(xù)】
[ 本帖最后由 dulao5 于 2007-9-29 15:47 編輯 ] |
|