测试可变长度参数函数的位标志


test for bitwise flag for variable length argument function

我有一个函数,我想使可变长度,最后一项可选的是类常量的位掩码。然而,我想不出一种方法来检查最后一项是否为位掩码而不是其他东西,因为它应该是可选的。

class D {
    const A = 1;
    const B = 2;
    const C = 4;
    const D = 8;
    public function test(){
      $args = func_get_args();
      $possibly_flags = $args[count($args)-1];
      if(???){ // do some test here to find out
          // do stuff with the flags check
      }
    }
}
$d->test($val1, $val2, [...,], D::A|D::B); 

有什么办法可以做到吗?

最后用一个不同的类来保存标志,以及它的任何其他设置,然后测试它是否是那个类的实例。由于该类将仅用于此目的,因此它的效果相当不错。我现在使用的示例如下:

class D {
    const A = 1;
    const B = 2;
    const C = 4;
    const D = 8;
    public function test(){
      $args = func_get_args();
      $possibly_flags = $args[count($args)-1];
      if($possibly_flags instanceof Settings){
          // do stuff with the flags
      }
    }
}
class Settings(){
    public $flags;
    public function __construct($flags){
        $this->flags = $flags;
    }
}
$d->test($val1, $val2, [...,], new Settings(D::A|D::B));

传递两种不同类型的数据,因此在函数声明中需要两个不同的参数:

public function test(array $args, $flags = 0)
{
}
...
$d->test([$var1, $var2, $var3], D::A);

我建议一个更透明的类设计:

class D {
    const A = 1;
    const B = 2;
    public function setBitmask($bitmask) {
        $this->bitmask = $bitmask;
        return $this;
    }
    public function test() {
        $args = func_get_args();
        if ($this->bitmask /* whatever */) {
            /* whatever else */
        }
    }
    protected $bitmask = self::A | self::B;
}

可以称为(new D())->setBitmask(D::A)->test($x, $y);

如果您坚持使用给定的参数——可变长度函数,最后一个参数是可选的——那么您将需要使用哨兵来区分两者。例如,如果null是哨兵:

(new D())->test($val1, $val2, null, D::A)

然后在你的方法中:

public function test() {
    $args = func_get_args();
    if (null === $args[count($args)-2]) {
        $bitmask = $args[count($args)-1];
        /* here you would check that bitmask is possible */
    } else {
        $bitmask = D::A; /* default if you want it */
    }
    if ($bitmask /* whatever */) {
        /* whatever else */
    }
}

这会变得非常糟糕和脆弱,所以一定要考虑我上面描述的accessor方法或@Jack的两个参数的方法。