- 论坛徽章:
- 0
|
尽管开发和运行环境早已经是php5了,但是一直没有使用php5的OO特性写代码。现在终于有机会拿着研究C++ OOP的精神,研究PHP5的OO特性。本文设计到一些细节,有些代码仅仅为了测试,有意为之,不要见笑。
(研究的是不是有点晚了,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();
?>
|
发现在ClassA里面直接以ClassB::foo();的形式“静态调用”,ClassB::foo();里面的this的确是对象$A的引用。
注意是“静态调用(called statically)”而非静态方法。经过测试,静态方法内不允许this伪变量。
上面的特性-- 在方法被静态调用的上下文环境中,this是调用者的引用,这个特性可以应用到多级继承时,提供子类访问基类的途径:
<?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不是太严格,甚至允许$obj->__construct , 当然这也可能是为了兼容以前的代码。
但是下面的测试很意外,ClassA::__construct()的调用引起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已经更正了这个bug,现在运行ClassAAA::__construct();会得到一个严重错误:
Fatal error: Non-static method ClassAAA::__construct() cannot be called statically in /usr/home/duzhigang/php5/test_construct.php on line 10
从手册看到一句话:
这是因为对象的析构时机依赖php的实际实现,可能在php销毁对象的时候,代码块已经不在我们的try catch控制中了。
对于我下面测试的这个版本,php在一个对象的引用计数为0时,立即调用析构函数进行销毁,所以有幸能捕获到析构函数内的异常。
但是手册里面的这个“注意”是对的,因为php没有明确定义析构函数执行的时机,所以我们不应该在析构函数中抛出异常。
<?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();
}
?>
|
【未完待续】
[ 本帖最后由 dulao5 于 2007-9-29 15:47 编辑 ] |
|