加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

使用类getter或类属性? (PHP)

发布时间:2020-12-13 17:10:14 所属栏目:PHP教程 来源:网络整理
导读:在内部使用属性时,编写OOP类的最佳实践是什么. 考虑以下课程; ?phpClass Foo{ /** * @var null|string */ protected $_foo; /** * @return null|string */ public function getFoo() { return $this-_foo; } protected function _doSomething() { $foo = $th
在内部使用属性时,编写OOP类的最佳实践是什么.

考虑以下课程;

<?php
Class Foo
{
    /**
     * @var null|string
     */
    protected $_foo;

    /**
     * @return null|string
     */
    public function getFoo()
    {
        return $this->_foo;
    }

    protected function _doSomething()
    {
        $foo    = $this->_foo;
        $result = null;
        // ...
        return $result;
    }
}

正如你所看到我在_doSomething()中使用属性_foo,尽管子类可以覆盖getFoo(),返回一个未存储回_foo的计算值;这是一个缺陷.

我该怎么办?

>将getter标记为final,在内部使用属性(无需额外的函数调用,强制最终开发人员将_foo用作属性,因为它受到保护)
>在内部使用getFoo(),将_foo标记为私有(额外函数调用)

两个选项都是防水的,但我非常关注所有额外的函数调用,所以我倾向于使用选项1,但选项2将更“真实的OOP”imho.

另请阅读http://fabien.potencier.org/article/47/pragmatism-over-theory-protected-vs-private,其中也建议选项2:/

另一个相关问题;
如果某个属性有一个setter,那么该属性应该是私有的,强制最终开发人员在子类中使用它,还是应该是一个不成文的规则,程序员有责任设置一个有效的属性值?

解决方法

正如你所说,第二种方法是根据OOP更正确的方法.你在调用方法的CPU周期方面比在作为变量访问属性方面花费更多的成本也是对的.但是,在大多数情况下,这将属于微优化的范畴.它不会对性能产生明显影响,除非所涉及的值被大量使用(例如在循环的最内部).除非表演真正受到影响,否则最佳做法倾向于偏向于最佳表现.

对于简单变量,内部使用getter并不是很明显,但如果您正在处理从外部数据源(如数据库)填充的属性,则该技术会自成一体.使用getter允许您以懒惰的方式从DB中获取数据,即在需要时而不是在需要之前.例如:

class Foo
{
    // All non-relevent code omitted
    protected $data = NULL;

    public class getData ()
    {
        // Initialize the data property
        $this -> data = array ();
        // Populate the data property with a DB query
        $query = $this -> db -> prepare ('SELECT * FROM footable;');
        if ($query -> execute ())
        {
            $this -> data = $query -> fetchAll ();
        }
        return ($this -> data);
    }

    public function doSomethingWithData ()
    {
        $this -> getData ()
        foreach ($this -> data as $row)
        {
            // Do processing here
        }
    }
}

现在使用这种方法,每次调用doSomethingWithData时,结果都是对getData的调用,而getData又调用了数据库查询.这很浪费.现在考虑以下类似的类:

class Bar
{
    // All non-relevent code omitted
    protected $data = NULL;

    public class getData ()
    {
        // Only run the enclosed if the data property isn't initialized
        if (is_null ($this -> data))
        {
            // Initialize the data property
            $this -> data = array ();
            // Populate the data property with a DB query
            $query = $this -> db -> prepare ('SELECT * FROM footable;');
            if ($query -> execute ())
            {
                $this -> data = $query -> fetchAll ();
            }
        }
        return ($this -> data);
    }

    public function doSomethingWithData ()
    {
        foreach ($this -> getData () as $row)
        {
            // Do processing
        }
    }
}

在这个版本中,你可以随意调用doSomethingWithData(实际上是getData),你永远不会触发多个数据库查找.此外,如果从不调用getData和doSomethingWithData,则不会进行任何数据库查找.这将带来巨大的性能提升,因为数据库查找很昂贵,应尽可能避免.

如果你在一个可以更新数据库的类中工作,它确实会导致一些问题,但它并不难解决.如果一个类对其状态进行更新,那么可以简单地对您的setter进行编码,以便它们在成功时将其关联状态置零.这样,下次调用getter时,数据将从数据库刷新.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读