"错误的类设计可能会改变本不应该改变的成员属性。"这个问题是在看 Java 的时候书中提到的。PHP5 默认传递的也是引用,那么可能也存在这个问题。于是跳下床来,做了个试验。果然……
先看一段代码:
 <?php  
/** 
 * privateClass  
 * 
 * 一个私有的类,在 publicClass 中使用 
 */ 
class privateClass 
{ 
    /** 
     * name 
     * 
     * 保存一个名字  
     *  
     * @var string 
     * @access protected 
     */ 
    protected $name = ''; 
    /** 
     * __construct 
     * 
     * 构造函数  
     *  
     * @param string $name  
     * @access public 
     * @return void 
     */ 
    public function __construct($name) 
    { 
        $this->setName($name); 
    } 
    /** 
     * getName  
     * 
     * 获得名字 
     *  
     * @access public 
     * @return string 
     */ 
    public function getName() 
    { 
        return $this->name; 
    } 
    /** 
     * setName 
     * 
     * 设置名字  
     *  
     * @param string $name  
     * @access public 
     * @return void 
     */ 
    public function setName($name) 
    { 
        $this->name = $name; 
    } 
} 
/** 
 * publicClass  
 * 
 * 公共类 
 */ 
class publicClass 
{ 
    /** 
     * priClass  
     *  
     * @var privateClass 
     * @access protected 
     */ 
    protected $priClass = null; 
    /** 
     * __construct 
     * 
     * 构造函数  
     *  
     * @param string $name  
     * @access public 
     * @return void 
     */ 
    public function __construct($name) 
    { 
        // 生成 privateClass 的对象 
        $this->priClass = new privateClass($name); 
    } 
    /** 
     * getName 
     * 
     * 返回名字  
     *  
     * @access public 
     * @return string 
     */ 
    public function getName() 
    { 
        // 返回名字 
        return $this->priClass->getName(); 
    } 
    /** 
     * getPrivateClass 
     * 
     * 返回私有类  
     *  
     * @access public 
     * @return privateClass 
     */ 
    public function getPrivateClass() 
    { 
        // 获取私有类对象 
        // return clone $this->priClass; 
        return $this->priClass; 
    } 
} 
// 生成了名为 ‘Foo’的对象 
$Foo = new publicClass('Foo'); 
// 取得了‘Foo’的私有对象 
$priClass = $Foo->getPrivateClass(); 
// 开始一些操作 
// 
// 使用 $priClass 对象时进行了一些操作,比如临时改了名字 
$priClass->setName('Bar'); 
//  
// 结束一些操作 
// 然后再次取得‘Foo’对象的名字,但是却发生了改变。 
echo $Foo->getName(); 
?> 
  
代码本身很好理解,看注释就应该能明白。正常来说 $Foo->getName() 得到的应该是 Foo。对引用比较熟悉的朋友会立刻指出,不对 $Foo->getName() 应该是 Bar。
没错是 Bar!但是这似乎不是在设计这两个类时希望得到的结果。publicClass 类并没有设置 setName 的成员方法,也隐含着 publicClass 不允许修改名字。但是由于某些原因,在编码时获得了 privateClass 的实例,可能由于逻辑需要临时改变了这个对象的一些属性。OK,作为一个临时变量,这没什么。但是作为引用,这就有问题了。
实际上绕过了类 publicClass 在名字这个属性上的约束,让不可变的属性发生了改变。很糟糕不是么?
不知道谁在自己的项目中使用过 clone 这个语法结构。我从来没有用过,之前总认为这个是没什么用的时髦玩意。但是PHP 语言本身也是相当精巧的。这个没用的玩意在这里居然有了用途:
    public function getPrivateClass() 
    { 
        // 获取私有类对象 
        return clone $this->priClass; 
    } 
将 publicClass::getPrivateClass() 方法改为上面的写法时,问题解决了……
这样看来 PHP 的反射应该也是非常有用的。嗯,继续研究,继续研究……
路漫漫……其修远……
Leave a Reply