伪重载的私有属性


Private properties for pseudo-overloading

假设我有一个这样的类:

class Foo{
    public function bar($p,$p2=null,$p3=null){
        //...
    }
}

有时我需要称它只传递第一个和第三个参数。问题是我必须放置第二个参数,传递任何东西,只是为了达到第三个。

我可以为可选参数创建私有属性和 setter 方法,并将它们从方法签名中删除。

这是一个好的做法吗?还是最好使用__callfunc_get_args

我在 SO 中读到的消息来源:

  • 什么是 php 中的函数重载和覆盖?
  • PHP 函数重载

并在手册中:

  • http://www.php.net/manual/en/language.oop5.overloading.php
  • http://www.php.net/manual/en/function.func-get-args.php

我可以为 可选参数并将其从方法签名中删除。

如果原因是您希望他们让开,那么这样做将是一个非常糟糕的主意。

什么是

参数,什么是属性是构成类设计的决策,因此只有在查看全局(与任何其他设计决策一样(之后,才应将一个交换为另一个。不要进行这种更改,因为您不喜欢一个特定方法的特定调用站点的读取方式。

我们无法判断参数是否有意义,因此对于其余部分,我将假设它没有意义。在这种情况下有哪些选择?

选项 #1:重构

  • 在此方法上有两个可选参数是否有意义?
  • 您通常在调用它时会省略其中一个(或两个(吗?

如果这些问题的答案是"是",这可能表明该方法根据参数以不同的模式运行。在这种情况下,将模态行为分解为具有简化签名的单独方法是有意义的。

选项 #2:属性捆绑

  • 此方法是否有很多具有合理默认值的参数?
  • 您是否通常在典型呼叫中仅提供其中的几个(或不提供(这些?

如果这些问题的答案是"是",那么你可以让该方法接受数组作为其最后一个参数,并将其用作"杂项选项"的容器。

这种方法有一个(很大的!(缺点,即这些选项不再通过方法签名进行通告,但如果存在合理的默认值,您不会在 90% 的时间内触及,那么它是有意义的。

选项#3:流畅的界面

如果可以指定很多选项,那么创建一个流畅的接口是有意义的,但这是一个很大的变化,除非有额外的参数(例如,如果需要可组合性(,否则不应该进行。您可以将流畅的接口视为将参数转换为属性的更好工程版本。

编写一个流畅的接口涉及一个新类,该类封装了可能进入函数调用的所有参数;该类对每个参数都有一个方法,以及一个或多个使用这些参数来执行工作的方法。一个流畅的接口调用站点看起来像

$foo->bar()->color('red')->type('widget')->execute();

此处$foo->bar()返回封装类的实例,colortype是该类上设置属性并execute读取这些属性并执行实际工作的方法。

你怎么能用funct_get_argscall来定义哪个参数是第二个或第三个参数?只有当它们具有不同的类型时,才有可能。

在我看来,如果您想要一种强大的方法来处理许多可能是可选的参数,请使用像捆绑对象这样的容器(通用或特定于您的函数(,或者更友好的关联数组。