为什么当扩展类时,PHP的私有变量变为公共的
为什么当扩展类时,PHP的私有变量变为公共的
我创建了以下类
PHP版本5.5
abstract class Model { var $id; private $cName; private $tName; public function __construct($id = 0) { $this->cName = '我是cName'; $this->tName = '我是tName'; } }
然后是一个扩展类
class claseExtend extends Model { var $id; public function hola() { $this->id = 1; return (array) $this; } }
如果我执行以下代码:
$obj = new claseExtend() ; $retHola =$obj->hola(); print_r($retHola);
我期望得到:array(id => 1)
但输出却是:array( \u0000Model\u0000cName: => '我是cName',
\u0000Model\u0000tName => '我是tName')
我做错了什么,或者为什么私有属性会被包括在数组转换中?
谢谢你的帮助。
PHP中的私有变量在继承类时变为公共的是因为print_r函数的特殊性。print_r是一种用于显示类的调试实用函数,可以显示包括私有和受保护的属性。根据PHP手册的描述,print_r、var_dump和var_export函数也会显示PHP 5中对象的受保护和私有属性,但不会显示静态类成员。
在PHP中,私有属性是会在派生类中继承的,但是它们是不可访问的。奇怪的是,如果将print_r替换为return,返回的结果是相同的。
但是,他并没有在对象上使用print_r()函数,而是使用(array)$this将对象转换为数组,并打印这个数组。问题是为什么类型转换包括了私有属性。
解决方法是在派生类中使用protected修饰符来修饰属性,这样就可以在派生类中访问这些属性,但是在类外部仍然是不可访问的。下面是修改后的代码示例:
class ParentClass { private $privateVariable = "Private Variable"; protected function printPrivateVariable() { echo $this->privateVariable; } } class ChildClass extends ParentClass { public function accessParentPrivateVariable() { $this->printPrivateVariable(); } } $child = new ChildClass(); $child->accessParentPrivateVariable(); // Output: Private Variable
在这个示例中,通过在ParentClass中使用protected修饰符来修饰privateVariable属性,然后在ChildClass中可以通过调用printPrivateVariable方法来访问这个属性。但是在类外部仍然无法访问privateVariable属性。
当你将对象转换为数组时,私有和受保护的属性会包含在结果中。文档中提到:
如果将对象转换为数组,结果将是一个数组,其元素为对象的属性。键是成员变量的名称,有一些特殊情况:整数属性是不可访问的;私有变量的变量名前面加上类名;受保护的变量的变量名前面加上“*”。这些添加的值两边都有空字节。
这些空字节在你的结果中显示为\u0000
。
感谢你的回答,我不明白为什么私有成员可以被这样访问。
它们被赋予了非常奇怪的名称,所以很难无意中访问它们。
出现这个问题的原因是PHP在将对象转换为数组时,为了保持对象的封装性,将私有变量的名称前面添加了类名作为前缀。这样做的目的是为了避免意外访问私有变量。私有变量的名称被修改后,就变得非常奇怪,使得无法直接访问到它们。
然而,虽然私有变量的名称被修改,但它们的值仍然可以通过类的方法进行访问。这样做的好处是可以保护对象的封装性,防止外部代码直接访问私有变量,从而避免意外修改对象的状态。
解决这个问题的方法是在子类中使用父类的方法来访问私有变量。由于父类的方法可以访问它的私有变量,因此可以通过在子类中调用父类方法的方式来获取私有变量的值。
总之,尽管PHP在将对象转换为数组时会将私有变量的名称进行修改,但这种修改仅仅是为了保护对象的封装性,防止意外访问和修改私有变量的值。通过使用父类的方法来访问私有变量,可以解决这个问题。这样做既能保护对象的封装性,又能获取私有变量的值。