PHP中如何访问父类中子类的私有属性

4
我有一个父对象,用于在我的应用程序中进行通用CRUD操作——它具有基本的保存和检索方法,因此我不必在所有对象中重新包含它们。我的大多数子对象都扩展了这个基础对象。这一直很好用,但是我发现一个问题,就是检索序列化的子对象时出现问题。我在父对象中使用“retrieve”方法创建一个子对象实例,然后从未序列化的子对象的属性中填充自己,这意味着它可以“自我反序列化”对象。
唯一的问题是,如果子对象具有受保护或私有属性,则父对象无法读取它,因此在检索过程中不会被捕获。
因此,我要么寻找更好的“自我反序列化”方式,要么允许父对象“看到”受保护的属性——但仅在检索过程中。
以下是代码示例:
BaseObject {

 protected $someparentProperty;

 public function retrieve() {

  $serialized = file_get_contents(SOME_FILENAME);
  $temp = unserialize($serialized);
  foreach($temp as $propertyName => $propertyValue) {
    $this->$propertyName = $propertyValue;
  }     

 }

 public function save() {

    file_put_contents(SOME_FILENAME, serialize($this));
 }
}

class ChildObject extends BaseObject {

 private $unretrievableProperty;  

 public setProp($val) {
    $this->unretrivableProperty = $val;
 }
}

$tester = new ChildObject();
$tester->setProp("test");
$tester->save();

$cleanTester = new ChildObject();
$cleanTester->retrieve();
// $cleanTester->unretrievableProperty will not be set

编辑:应该说“私有”而不是受保护的子属性。

4个回答

3

试试这样:

abstract class ParentClass
{
  protected abstract function GetChildProperty();

  public function main()
  {
    $value = $this->GetChildProperty();
  }
}

class ChildClass extends ParentClass
{
  private $priv_prop = "somevalue";

  protected function GetChildProperty()
  {
    return $this->priv_prop;
  }
}

0

修复此问题的最佳方法是使用反射

示例:

$_SESSION[''] = ''; // init

class Base {
    public function set_proxy(){
        $reflectionClass = new ReflectionClass($this);
        $ar = $reflectionClass->getDefaultProperties();

        !isset($ar['host'])  or  $_SESSION['host'] = $ar['host'];
    }
}

class Son1 extends Base {
    private $host = '2.2.2.2';
}

class Son2 extends Son1 {

}


$son1 = new Son1();
$son1->set_proxy(); 
var_dump($_SESSION); // array(2) { [""]=> string(0) "" ["host"]=> string(7) "2.2.2.2" }

unset($_SESSION);
$_SESSION[''] = ''; // init

$son2 = new Son2();
$son2->set_proxy(); 
var_dump($_SESSION); //  array(1) { [""]=> string(0) "" }

0

似乎继承/父类并不适用于相同的类可见性策略。PHP文档没有涉及这个问题。

我建议您将retrieve方法声明为静态,并通过静态调用获取$cleanTester,而不是当前的“self unserialize”方法。

static function retrieve() {
  $serialized = file_get_contents(SOME_FILENAME);
  return unserialize($serialized);
}

[...]

$cleanTester = BaseObject::retrieve();

或者你可以利用__get()方法来访问不可访问的属性...我相信这可以添加到BaseObject类中,并从子类获取受保护的属性。由于相同的类可见性策略应该适用于BaseObject,所以你可以将__get()方法定义为私有或受保护。

BaseObject {
  private function __get($propertyName) {
    if(property_exists($this,$propertyName))
      return $this->{$propertyName};

    return null;
  }

谢谢。静态方法似乎可行 - 但是一些子对象需要被实例化,并在它们能够确定应该从哪个文件名中检索之前进行一些处理。__get已经用于这个目的,但是当我迭代对象的属性时,父对象不知道要请求哪些属性。我想我需要看一下迭代方法 - 感谢指针。 - Hippyjim

0
子对象中加入一个getProperty()函数,返回$this->unretrievableProperty属性,这个怎么样?

谢谢 - 很好的想法,但是作为基本对象,它无法知道子对象的属性,也就不知道该请求什么。 - Hippyjim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接