【问题标题】:Not able to access private protect member in iterator php无法访问迭代器 php 中的私有保护成员
【发布时间】:2013-02-14 12:38:57
【问题描述】:

这里是数据迭代器的实现

//Data Iterator 
    class DataIterator implements Iterator
    {
        public $data ;
        public function __construct(Data $obj)
        {
            $this->data = $obj;
        }
        public function rewind()
        {
            $this->properties = get_object_vars($this->data);                       
        }
        public function valid()
        {
            if (key($this->properties) === null )
            {
                return false;
            }   
            return true;
        }
        public function key()
        {
            return key($this->properties);
        }
        public function current()
        {
             return current($this->properties);
        }
        public function next()
        {
            next($this->properties);
        }

    }

这里是数据类

 /*Data Class*/
    class Data implements IteratorAggregate
    {
        public $name; 
        private $age;
        protected $address;
        public $country;
        public $state;

        public function __construct($name, $age, $address, $country = 'USA', $state = 'NH')
        {
            $this->name = $name;
            $this->age = $age;
            $this->address = $address;
            $this->country = $country;
            $this->state = $state;
        }
        function getIterator()
        {       
            return new DataIterator($this);
        }
    }

这里是调用部分

$data = new Data('Joker', '27', 'California');

    foreach($data->getIterator() as $key => $value)
    {
        echo $key , ' ', $value, '<br>';
    }  

输出

name Joker
country USA
state NH

请注意,输出不包含我的私有和受保护属性(年龄、地址)输出。

我如何告诉 Iterator 也输出这些?

【问题讨论】:

    标签: php iterator


    【解决方案1】:

    您不能告诉迭代器输出这些属性,因为它们根本无法从外部访问(即迭代器执行get_object_vars($this-&gt;data) 的点。

    有两种方法可以做到这一点:

    1. 通过让数据对象将值传递给迭代器。
    2. 使用反射 API 将它们强行拉出(冗长、缓慢!)。

    但在继续使用 #1 作为首选选项之前,请停下来问问自己:为什么迭代器会暴露数据对象的非公共成员?

    做某事private 的意思是“你们真的不需要知道这件事;它可能会在未来消失,或者它可能会变得面目全非”。如果是外界关心的东西,那为什么不是public(直接暴露,或者通过公共getter暴露)?重新考虑一下这个迭代器的目的是什么。

    也就是说,这就是你将如何做#1:

    class DataIterator implements Iterator
    {
        public $data;
        private $properties;
        public function __construct(Data $obj, array $propeties)
        {
            $this->data = $obj;
            $this->properties = $properties;
        }
    
        public function rewind()
        {
            // Arguably horrible trick to refresh the property map without
            // demanding that Data exposes a separate API just for this purpose
            $newIterator = $this->data->getIterator();
            $this->properties = $newIterator->properties;
        }
    }
    
    class Data implements IteratorAggregate
    {
        function getIterator()
        {       
            return new DataIterator($this, get_object_vars($this));
        }
    }
    

    【讨论】:

      【解决方案2】:

      Public、private 和 protected 是访问修饰符。它们旨在限制类属性的可访问性。

      • Public 意味着任何人都可以访问该属性,因此如果有人愿意,他们可以更改值,而您并不知道。
      • Private 表示该属性只能在类内部访问, 所以没有人可以“弄乱”类外部的这些属性。
      • Protected 类似于 Private,但是子类(那些 从该类继承)可以访问它。

      您将ageaddress 设为私有,所以您基本上是在说,不允许任何人访问这些属性。如果您想访问私有/受保护的属性,则必须创建 getter 和 setter 并调用这些函数,或者将属性设为公开。

      【讨论】:

        【解决方案3】:

        尝试 get_class_vars

        $this->properties = get_class_vars(get_class($this->data));
        

        而不是 $this->properties = get_object_vars($this->data);

        【讨论】:

          猜你喜欢
          • 2015-01-30
          • 2016-07-15
          • 2011-01-02
          • 1970-01-01
          • 1970-01-01
          • 2012-05-03
          • 1970-01-01
          • 1970-01-01
          • 2016-05-22
          相关资源
          最近更新 更多