PHP类的load()方法是好的还是不好的实践?

3

我想知道您是否能够分享一些最佳实践?

在一个类中添加一个 load 方法是正确/最佳的方式吗?

Class Test extends Foo{

    public $id;
    public $name;

    public function __construct()
    {
        parent::__construct();

    }

    public function load($id, $name)
    {
        $this->id = $id;
        $this->name = $name;
    }
}

或者,是否认为将load方法逻辑放在构造函数中是更好的实践呢?
Class Test extends Foo{

    public $id;
    public $name;

    public function __construct($id, $name)
    {
        parent::__construct();

        $this->id = $id;
        $this->name = $name;
    }
}

第二个选项对我来说更合理,它只有一个方法并且被自动调用,但是我经常看到使用第一个选项。这是有原因的吗?感谢任何帮助!

这与延迟加载密切相关 - 请参见http://en.wikipedia.org/wiki/Lazy_loading - Sam Dufel
@SamDufel:我看不出相似之处? - Madara's Ghost
@MadaraUchiha - 惰性加载背后的一般思想是在不初始化所有数据/资源的情况下实例化对象;直到它们实际需要时才等待初始化(“加载”)它们。 - Sam Dufel
@SamDufel:不是很准确,根据定义,你无法实例化一个对象而没有它的所有依赖项。通常通过回调或某种缓存形式等待获取所有这些依赖项,然后才实例化实际对象。直到您拥有所有依赖项,该对象本身才会被实例化。 - Madara's Ghost
@MadaraUchiha,我理解你的意思,在某些情况下我会同意,但在某些情况下,Foo可能只是一个基本的CRUD类。我真的没有任何实际原因放进去,只是一个“为什么不呢”的想法。问题主要是关于构造函数是否只做加载是否是一件坏事。谢谢。 - Rwd
显示剩余3条评论
4个回答

3
第二个选项更好。构造函数的作用是为对象做准备。它是初始化属性等的理想场所。除非你有使用load()而不是构造函数的充分理由,否则请使用第二个示例。

1
第一个选项使用了稍微多一点的抽象,我想。
我可以看到有些情况下你可能需要复制代码并将变量赋值分离到 load()init() 函数中,这样做可能会让你的代码更容易更新以适应新的目的。

0

第一种选择的优点是您不需要立即向开发人员提供信息。虽然这更容易出错,因为有可能会忘记调用加载函数。如果所有其他函数都需要设置 $id 和 $name,则最好在创建新对象时要求参数。

另一方面,没有加载函数可以防止您在代码后期重新加载具有新值的对象。

您可以通过从构造函数调用加载函数来将两者结合起来:

Class Test extends Foo{

    public $id;
    public $name;

    public function __construct( $id, $name )
    {
        parent::__construct();
        $this->load( $id, $name );
    }

    public function load($id, $name)
    {
        $this->id = $id;
        $this->name = $name;
    }
}

如果您不需要在创建时设置值,您可以使用PHP的有趣函数重载功能:

Class Test extends Foo{

    public $id;
    public $name;

    public function __construct()
    {
        parent::__construct();
        if( func_num_args() === 2 ){
            call_user_func_array(array($this, 'load'), func_get_args() );
        }
    }

    public function load($id, $name)
    {
        $this->id = $id;
        $this->name = $name;
    }
}

我只是因为魔法而-1。真的吗?阅读您类的公共API,您能猜到可以将项目传递给构造函数吗? - Madara's Ghost
我猜如果你正在编写一个公共API,你会添加PHPdoc或其他类型的文档,解释构造函数有可选参数。这样可以为未来的开发人员清晰明了。此外,这只是第一个示例的另一种选择,我更喜欢这个。 - Maarten Bicknese
常见误解。你的代码应该尽可能自我描述。你刚刚成功地引入了魔法。魔法是邪恶的。不要引入魔法。你要么在生成时需要它们,要么就不需要。不要试图想要蛋糕又想吃掉它 :) - Madara's Ghost

-2

你可以针对特定成员扩展load()函数。

将每个属性设置为protected或private,并为其中一个属性提供set/get函数。这是一种可接受的方式,有时比在构造函数中重载依赖项和逻辑更好。

尝试这样做,看看是否有帮助:

    Class Test extends Foo{

    protected $id;
    protected $name;

    public function __construct()
    {
        parent::__construct();
    }

    public function setId($id) {
        $this->id = $id;
    }

    public function setName($name) {
        $this->name = $name;
    }

    public function getId() {
        return $this->id;
    }

    public function getName() {
        return $this->name;
    }
}

它被称为“获取器和设置器”,是一种更干净、更健壮的方法。此外,正如其他回答中提到的 - 它提供更好的可重用性、使对象保持干净,没有空值的数据,但这完全取决于您的类的意图!

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