将很多参数传递给parent :: __构造代码异味/差OOP?

时间:2011-12-12 18:32:08

标签: php oop class inheritance constructor

我正在编写一些代码,我开始对凌乱的parent::__construct电话感到有点不舒服,我首先想知道的是,这是不好的OOP练习,其次是有更清洁的方法吗?请参阅触发我问题的下面特别极端的示例。

<?php
class BrowseNodeLookupRequest extends Request {

    protected $BrowseNodeId;

    public function __construct($Service, $AWSAccessKeyID, $AssociateTag,
            $Operation, $MerchantID = null, $ResponseGroup = null,
            $Version = null, $Style = null, $ContentType = null,
            $XMLEscaping = null, $Validate = null, $BrowseNodeId) {
        parent::__construct($Service, $AWSAccessKeyID, $AssociateTag,
                $Operation, $MerchantID, $ResponseGroup, $Version, $Style,
                $ContentType, $XMLEscaping);
        $this->setBrowseNodeId($BrowseNodeId);
    }

    protected function setBrowseNodeId($BrowseNodeId) {
        if (is_string($BrowseNodeId)) {
            $this->BrowseNodeId = $BrowseNodeId;
        } else {
            throw new Exception('BrowseNodeLookupRequest Parameter (BrowseNodeId
                                 ) Must be a String');
        }
    }

}
?>

4 个答案:

答案 0 :(得分:3)

对任何函数都有很多参数是不好的做法,无论是__parent::construct还是{。}}。

这太容易搞砸了,特别是在PHP中。很多时候,这表明您缺少物体(或者部件之间的耦合太紧)。如果你不能提出任何其他缺失的对象,我甚至更愿意传递一个“配置”对象。

class ConfigFoo
{
  public $Service, $AWSAccessKeyID, ..., $foo, $bar;
}

$cfg = new ConfigFoo();
$cfg->Service = 'whatever';
...

$req = new BrowseNodeLookupRequest($cfg);

这基本上是一种传递参数数组的更结构化的方法。配置对象可以扩展其他配置对象以跟随其他对象。

当然,课程可以比简单的公共属性更先进。您可以管理数据完整性等等。

要明确:除非a)没有其他缺少的中间对象,否则我不会求助于上述情况; b)有足够数量的参数使得使用简单数组就像一长串函数一样有问题参数。

答案 1 :(得分:1)

Waaaay太多的快递IMO。 Id要么传入一个数组,要么可能将关注点分离到各种模型中,然后通过构造函数将它们注入到对象中。

答案 2 :(得分:0)

调用parent :: __ construct();

绝对不错

在php中,这可能并不总是必要的,因为如果父项具有自己的构造函数并且子类没有定义构造函数,则会自动调用父项的构造函数。

相比之下,在Java中没有这样的奢侈品,你总是需要在Java中调用父构造函数,所以这是你一直在Java中看到的东西,可能在其他允许重载构造函数方法的语言中。

答案 3 :(得分:0)

感谢所有评论者,尤其是Matthew,我采用的解决方案是从父类的构造函数方法中删除可选参数,并将它们添加到父类中可用的公共setter方法。修改后的代码如下所示。请注意,' - &gt; setValidate'和' - &gt; setResponseGroup'是从父类继承的新方法。显然,如果您处于类似情况但所有参数都是必需的,那么您需要选择响应中列出的其他选项之一。

修订班级:

<?php
class BrowseNodeLookupRequest extends Request {

    protected $BrowseNodeId;

    public function __construct($Service, $AWSAccessKeyID, $AssociateTag,
            $Operation, $BrowseNodeId) {
        parent::__construct($Service, $AWSAccessKeyID, $AssociateTag, $Operation);
        $this->setBrowseNodeId($BrowseNodeId);
    }

    protected function setBrowseNodeId($BrowseNodeId) {
        if (is_string($BrowseNodeId)) {
            $this->BrowseNodeId = $BrowseNodeId;
        } else {
            throw new Exception('BrowseNodeLookupRequest Parameter (BrowseNodeId
                                 ) Must be a String');
        }
    }

}
?>

用法示例:

<?php
$noderequest = new BrowseNodeLookupRequest($Service, $AWSAccessKeyID, $AssociateTag,
            $Operation, $BrowseNodeId);
//If the optional params are required//
$noderequest->setResponseGroup('Blah');
$noderequest->setValidate('True');
//etc.
?>