[英]'Named parameters' using arrays
我的項目中有一些實用程序類,正在考慮使用數組來創建“命名參數”。
我的代碼允許我鏈接方法或單獨使用它們。 例如,我有一個處理字符串的字符串類(有點明顯:))
現在,帶有鏈接的方法示例集如下所示:
print Utils\String::Set('my string')->UcFirst()->UcLast()->Get()
沒有鏈接的同一件事看起來像這樣:
$string = Utils\String::UcFirst('my string');
print Utils\String::UcLast($string);
這適用於某些方法,但是諸如“ Suffix”之類的方法存在問題,該方法具有以下參數:$ string,$ suffix。
這會導致連鎖問題,因為我最終會這樣做
Suffix(null, ' New')
看起來真的不是很好。
在這種情況下,使用數組可以提供命名參數嗎? 然后,我可以執行以下鏈接操作:
Suffix(['suffix' => ' New'])
但是,我不確定這將使維護項目變得困難多少,以及是否值得刪除非鏈接方法以致不需要數組。
我不會走這條路。 用數組代替命名參數的問題在於,您無法將參數定義為必需參數或可選參數,並且無法鍵入提示它們的參數,這將使查找錯誤或增加其他驗證要求更加困難。
如果您不知道該怎么做,請考慮使用該庫編寫代碼的方式。 任何IDE都可以快速顯示方法需要的參數,但是如果僅顯示array ,則必須仔細閱讀文檔。
我什至更進一步,將靜態方法與對象鏈接方法分開。 現在看來,可以使用值參數靜態調用String::Suffix
而不使用值參數靜態調用String::Suffix
。 除了違反E_STRICT標准外,這還將兩個完全不同的接口融合為一種方法。
namespace Util;
class String // you might want to change the name to "Strings", "string" is a reserved keyword in PHP 7
{
public static function Suffix($string, $suffix)
{
return (new StringWrapper($string))->Suffix($suffix);
}
}
class StringWrapper
{
private $value;
public function __construct($string)
{
$this->value = $string;
}
public function Suffix($suffix)
{
return new static($this->value . $suffix);
}
public function __toString()
{
return $this->value;
}
}
您會看到String
中的靜態接口只是StringWrapper
類中實際實現的一個瘦包裝。 StringWrapper
是不可變的值對象類型,並提供用於字符串操作的方法。 每個方法調用都會返回該類的新實例,該實例保存修改后的值。 使用__toString
您最終可以將其轉換為標量字符串值(這是使用Get()
方法執行的操作)
Voilà,不再需要命名參數
看來您正在做的是將前綴從函數應用程序的前綴轉換為前綴表示。 也就是說,您正在編寫x1->f(x2,…,xn)
而不是f(x1,x2,…,xn)
x1->f(x2,…,xn)
。
您始終可以只使用前綴表示法來編寫S::UcLast(S::UcFirst("my string"))
。 簡潔性是通過use Utils\\String as S
。
要將->
用作中綴符號的一部分,您需要一個類似於以下內容的類定義(並且我假設您的實現也是如此)。
class UtilStringProxy
{
public $string;
public function __construct($string)
{
$this->string = $string;
}
public function UcFirst()
{
$this->string = S::UcFirst($this->string);
return $this;
}
public function UcLast()
{
$this->string = S::UcLast($this->string);
return $this;
}
public function Suffix($suffix)
{
$this->string = S::Suffix($this->string, $suffix);
return $this;
}
}
第一個論點被揭穿。 這就是我們使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
,如果要立即應用,請使用->call(x)
。
使用這個可以寫從左到右的合成:
(new Compose('strtolower'))->lr('ucfirst')->call("hEllo World")
或從右至左組成:
(new Compose('ucfirst'))->rl('strtolower')->call("hEllo World")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.