【问题标题】:Query array or object property?查询数组或对象属性?
【发布时间】:2017-08-15 03:21:21
【问题描述】:

我还是 OOP 的新手,这可能是一个简单的问题,不确定我是否想多了。

假设我们有一个像下面这样的简单类,我们可以用它来实例化一个可以生成数组的对象:

class gen_arr {

   public $arr = array();

   public function fill_arr() {
     $this->arr["key"] = "value";
   }

}

// instantiate object from gen_arr
$obj = new gen_arr();

现在如果你想获取 object 的 数组项的 value,你会先生成一个数组,然后回显这个值,例如:

$arr = $obj->fill_arr();

回声 $arr["key"];

或者你会直接访问对象的属性吗?

echo $obj->arr["key"]

在实际代码中,属性是私有的,并且有一个方法可以查看属性数组,以上只是为了简化问题。

当涉及到这种情况时,是否有性能考虑和/或只是最佳实践?

更新:

从答案中仍然不清楚最好的方法是从属性生成一个数组并访问该数组还是直接访问该属性(通过 getter 方法)

【问题讨论】:

  • 如果属性是public,这个类的意义何在?
  • 它将是私有的,并且会有一个 getter 方法,我只是将其作为示例。从答案中仍然不清楚最好的方法是从属性生成一个数组并访问该数组还是直接访问该属性(通过getter方法)
  • 嗯,目的是什么?你想达到什么目标?你想防止什么?
  • 我想访问属性内的数据,我只是不知道是应该“直接”访问它(通过 getter 方法),还是先从它生成一个数组

标签: php oop


【解决方案1】:

由于您仅使用 fill_arr 上的项目填充数组,因此在您调用 $arr = $obj->fill_arr(); 之前,这些项目将不可用。

如果你想直接调用数组,那么你必须像这样在这个调用的构造函数上填充这个数组:

class gen_arr {

   public $arr = array();

   function __construct() {
     $this->arr["key"] = "value";
   }

}

【讨论】:

    【解决方案2】:

    首先,您与我们分享的课程存在一系列问题:

    • 它的唯一实例属性是public,任何人都可以修改
    • 您有一些时间耦合,需要调用方法 fill_arr() 才能访问该值才有意义

    封装

    将实例属性的可见性从public降低到private,使该属性只能由对象本身修改,并提供访问器代替:

    class gen_arr
    {
        private $arr;
    
        public function fill_arr() 
        {
            $this->arr["key"] = "value";
        }
    
        public function arr()
        {
            return $this->arr;
        }
    }
    

    时间耦合

    删除方法fill_arr(),改为使用以下选项之一初始化属性$arr

    • 第一次访问时延迟初始化字段
    • 在构造函数中初始化字段
    • 使用默认值初始化字段
    • 使用通过构造函数注入的值初始化字段

    第一次访问时延迟初始化字段

    第一次访问时初始化该字段:

    class gen_arr
    {
        private $arr;
    
        public function arr()
        {
            if (null === $this->arr) {
                $this->arr = [
                    'key' => 'value',
                ];
            }
    
            return $this->arr;
        }
    }
    

    在构造函数中初始化字段

    在构造过程中赋值:

    class gen_arr
    {
        private $arr;
    
        public function __construct()
        {
            $this->arr = [
                'key' => 'value',
            ];
        }
    
        public function arr()
        {
            return $this->arr;
        }
    }
    

    使用默认值初始化字段

    直接给字段赋值,如果你不需要做任何计算就可以了:

    class gen_arr
    {
        private $arr = [
            'key' => 'value',
        ];
    
        public function arr()
        {
            return $this->arr;
        }
    }
    

    用构造函数注入的值初始化字段

    如果值不是硬编码或以其他方式计算的(如前面的示例),并且您需要能够实例化具有不同值的对象,请通过构造函数注入值:

    class gen_arr
    {
        private $arr;
    
        public function __construct(array $arr)
        {
            $this->arr = $arr;
        }
    
        public function arr()
        {
            return $this->arr;
        }
    }
    

    访问和取消引用值

    这似乎是您的实际问题,所以答案是 - 当然 - 这取决于!

    假设我们提供了一个访问器,而不是直接访问 public 字段:

    自 PHP 5.4 起,以下是可能的:

    $object = new gen_arr();
    
    echo $object->arr()['key'];
    

    如果您仍在使用旧版本的 PHP,您显然不能这样做,而必须这样做:

    $object = new gen_arr();
    
    $arr = $object->arr();
    
    echo $arr['key'];
    

    不过,这个问题的答案很大程度上取决于具体情况以及您想要达到的目标。毕竟,可读性是维护的关键,所以引入一个解释变量可能对你来说很有意义。

    注意关于您的示例,您可以改用ArrayObject

    $arr = new \ArrayObject([
        'key' => 'value',
    ]);
    
    echo $arr['key']);
    

    参考见:

    例如,请参阅:

    【讨论】:

      【解决方案3】:

      先填满数组

      $gen_arr = new gen_arr();
      $gen_arr->fill_arr();
      

      然后使用 getter 方法获取值

      $val = $gen_arr->getValue($key);
      

      getter 方法是这样的

      public function getValue($key) {
          return $this->arr[$key];
      }
      

      并且确定将 $arr 属性设为私有

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-25
        • 2021-11-06
        • 2010-12-30
        相关资源
        最近更新 更多