Php ';命名参数';使用数组

Php ';命名参数';使用数组,php,arrays,oop,methods,Php,Arrays,Oop,Methods,我的项目中有一些实用程序类,并考虑使用数组来创建“命名参数” 我的代码允许我链接方法或单独使用它们。例如,我有一个处理字符串的string类(有点明显:) 现在,带有链接的一组示例方法如下所示: print Utils\String::Set('my string')->UcFirst()->UcLast()->Get() $string = Utils\String::UcFirst('my string'); print Utils\String::UcLast($str

我的项目中有一些实用程序类,并考虑使用数组来创建“命名参数”

我的代码允许我链接方法或单独使用它们。例如,我有一个处理字符串的string类(有点明显:)

现在,带有链接的一组示例方法如下所示:

print Utils\String::Set('my string')->UcFirst()->UcLast()->Get()
$string = Utils\String::UcFirst('my string');
print Utils\String::UcLast($string);
而没有链接的同一事物看起来是这样的:

print Utils\String::Set('my string')->UcFirst()->UcLast()->Get()
$string = Utils\String::UcFirst('my string');
print Utils\String::UcLast($string);
这适用于某些方法,但诸如“后缀”之类的方法存在问题,该方法具有以下参数:$string、$Suffix

这会导致链接问题,就像我最终会做的那样

Suffix(null, ' New')
看起来不太好

在这种情况下,使用数组可以提供命名参数吗? 然后,我就可以为链接执行以下操作:

Suffix(['suffix' => ' New'])

但是,我不确定这会使维护项目变得多么困难,是否值得放弃非链接方法,这样就不需要数组。

看来您正在做的是将函数应用程序的前缀转换为中缀符号。也就是说,您编写的不是
f(x1,x2,…,xn)
而是
x1->f(x2,…,xn)

您总是可以使用前缀符号来编写
S::UcLast(S::UcFirst(“我的字符串”))
。简洁性来自
使用Utils\String作为S

要使用
->
作为中缀符号的一部分,您需要一个如下所示的类定义(我假设您的实现也是这样)

第一个论点被删去。这就是我们如何使
f
进入中缀位置(在操作数1和2之间)的方法。然后你可以写:

(new UtilStringProxy("my string"))->UcFirst()->UcLast()->Suffix("New")->string
就我个人而言,我不认为这是一种愿望:

S::Suffix(S::UcLast(S::UcFirst("my string")), "New")
补遗 函数组合是看待这一点的另一种方式。函数应用程序提供从左到右的读取,而函数组合可以通过翻转参数提供从左到右或从右到左的读取

带有
UtilStringProxy
的示例基本上是为特定函数集
UcFirst、UcLast、Suffix
定义的从左到右的函数组合。你可以从中归纳

class Compose
{
  public $f;

  public function __construct(callable $f)
  {
    $this->f = $f;
  }

  public function lr(callable $g)
  {
    $f = $this->f;
    return new Compose(function ($x) use ($f, $g) {
      return $g($f($x));
    });
  }

  public function rl(callable $g)
  {
    $f = $this->f;
    return new Compose(function ($x) use ($f, $g) {
      return $f($g($x));
    });
  }

  public function call($x)
  {
    $f = $this->f;
    return $f($x);
  }

}
我添加了
call
方法,因为PHP的解析器中有一个不幸的弱点,您无法编写
expr(x)
来将
expr
应用于任何表达式的
x
,只有一些表达式。如果您只想恢复合成的函数,请使用
->f
,如果您想立即应用它,请使用
->调用(x)

使用此选项,您可以从左到右撰写作文:

(new Compose('strtolower'))->lr('ucfirst')->call("hEllo World")
(new Compose('ucfirst'))->rl('strtolower')->call("hEllo World")
或从右到左组合:

(new Compose('strtolower'))->lr('ucfirst')->call("hEllo World")
(new Compose('ucfirst'))->rl('strtolower')->call("hEllo World")

我不会走这条路。用数组替换命名参数的问题在于,您不能将参数定义为必需的或可选的,也不能键入提示,这会使错误更难找到,或者增加额外验证的要求

如果您不熟记,请思考如何使用此库编写代码。任何IDE都可以快速显示方法所采用的参数,但如果它只显示数组,我必须仔细查看文档

我甚至会更进一步,将静态方法从对象链接方法中分离出来。现在看来,
String::Suffix
可以使用value参数静态调用,而不使用value参数非静态调用。除了违反E_严格的标准外,它还将两个完全不同的接口合并到一个方法中

以下是我将如何实现您的API: 您将看到
String
中的静态接口只是
StringWrapper
类中实际实现的一个薄薄包装
StringWrapper
是一种不可变的值对象类型,提供了字符串操作的方法。每个方法调用都返回一个包含修改后的值的类的新实例。使用
\uuu toString
您最终可以将其转换为标量字符串值(这是您使用
Get()
方法所做的)


瞧,不再需要命名参数了

谢谢您的回复。这个解决方案看起来更好,我必须同意在一个方法中有两个接口是个坏主意。您在StringWrapper::Suffix中使用了一个静态类,这是什么意思?我在PHP手册中找不到它。
newstatic
uses。如果您不打算允许
StringWrapper
的子类,您也可以编写
newself
newstringwrapper