PHP中的变量函数和类型提示

时间:2011-06-10 00:42:12

标签: php types variadic-functions type-hinting

快点:

有没有办法在PHP中强制执行可变参数函数的类型?我假设没有,但也许我错过了什么。

截至目前,我只是强制所需类型的一个必需参数,并迭代检查其余部分。

public function myFunction(MyClass $object){
    foreach(func_get_args() as $object){
        if(!($object instanceof MyClass)){
            // throw exception or something
        }
        $this->_objects[] = $object;
    }
}

有更好的解决方案吗?


目的:

一个容器对象,充当子对象的迭代列表,具有一些实用程序功能。使用可变参数构造函数调用它将是这样的:

// returned directly from include
return new MyParent(
    new MyChild($params),
    new MyChild($params),
    new MyChild($params)
);

另一个选项可能是addChild方法链:

$parent = new MyParent;
return $parent
    ->addChild(new MyChild($params))
    ->addChild(new MyChild($params))
    ->addChild(new MyChild($params));

孩子们也会对他们的构造函数提出几个论点,所以我试图在易读性和处理费用之间取得平衡。

2 个答案:

答案 0 :(得分:16)

现在是possible with PHP 5.6.x,使用...运算符(在某些语言中也称为splat运算符):

示例:

function addDateIntervalsToDateTime( DateTime $dt, DateInterval ...$intervals )
{
    foreach ( $intervals as $interval ) {
        $dt->add( $interval );
    }
    return $dt;
}

答案 1 :(得分:2)

好吧我会说它取决于参数的数量:)没有像列表一样(所有参数1-n为MyClass [在PHP 5.6之前,对于PHP 5.6+,请参阅Variadic functions]),它更多您需要编写每个参数(如在您的问题中),并且允许发送更多参数,但只会检查定义的参数。

但是,您可以定义更多并使其可选。因此我写它的原因取决于参数的数量:

public function myFunction(MyClass $object, MyClass $object2=null, MyClass $object3=null, MyClass $object4=null, ...){
    foreach(func_get_args() as $object){
        if(null === $object){
            // throw exception or something
        }
        $this->_objects[] = $object;
    }
}

通过这样的示例,当参数不是NULL而不是MyClass时,PHP会抛出异常(如果作为默认值给出,则传递NULL,is possible也可以传递)。可选参数不应该是func_get_args()的返回值的一部分。我的意思是,如果你没有传递第三个参数(这里名为$object3),它将不会出现在func_get_args()返回的数组中。

不知道这对你来说是否比问题中的代码更实用。

如果在代码中遇到更多这样的情况,可以创建某种帮助程序来验证函数调用的输入,并委托从助手中抛出异常错误消息。这样可以防止重复的代码,并且在开发过程中会更加舒适,因为您可以在为多个案例编写异常通知时使异常通知更好。


根据你的新反馈,如果你想首先让解释器,一点迭代和addMember函数执行它的工作:

class MyParent {
    private $children = array();
    public function __construct() {
        foreach(func_get_args() as $object) $this->addChild($object);
    }
    public function addChild(MyChild $object) {
        $this->children[] = $object;
    }
}

在任何列表中使用错误类型的对象实例化对象将阻止实例化集合。

然后你可以这样做:

// returned directly from include
return new MyParent(
    new MyChild($params),
    new MyChild($params),
    new MyChild($params)
);