注意:为了防止downvotes因为良好做法可能是基于意见的 - 您还可以将问题改为:类型检查返回的缺点是什么用于弥补PHP缺乏泛型的价值?(我没有使用它,因为它暗示 缺点)。
来自Java / C#世界,PHP的松散类型处理一直有点烦人。当引入输入参数的类型提示但我仍然缺少generics和返回值的类型提示时,它会变得更好。
我发现自己通过明确检查代码中的类型来解决这个问题 - 由于语言本身可以为我处理它而感觉有些错误 - 我想将这些问题推向社区:
为了更好地了解为什么会出现问题,请考虑以下示例:
假设我们正在构建一个框架来转换其他一些输出数据中的输入数据。示例:
通过xpath表达式选择所述DomDocument的标题,将表示XML文档的字符串转换为另一个字符串的DomDocument。
(string) $xml =[TransformToDomDocument]=> (DomDocument) $doc =[TransformToString]=> (string) $title
现在让我们假设输入不是包含XML但是包含Json的字符串(但保持相同的数据)。我们现在想要将Json输入转换为Json对象,并使用JsonPath表达式来选择标题。
(string) $jsonString =[TransformToJson]=> (Json) $jsonObject =[TransformToString]=> (string) $title
(注意:第二个例子应该澄清整个框架应该非常灵活。)
通过使用一系列适配器对象来执行转换,这些对象处理从输入到输出的转换:
interface AdapterInterface{
/**
* Transform some input data into something else.
* @param mixed $data
* @return mixed
*/
public function transform($data);
/**
* Set the Adapter that is used to preprocess the $data before calling $this->transform($data)
* @param AdapterInterface $adapter
*/
public function setPredecessorAdapter(AdapterInterface $adapter);
}
class XmlToDomDocumentAdapter implements AdapterInterface{
private $predecessor;
/**
* Transform an xml string into a DOMDocument.
* @param mixed $data
* @return DomDocument
*/
public function transform($data){
if($this->predecessor !== null){
$data = $this->predecessor->transform($data);
// At this point, we just have to "trust" that the predecessor returns a (string)
}
$doc = new DomDocument();
$doc->loadXml($data);
return $doc;
}
}
class DomDocumentToStringAdapter implements AdapterInterface{
private $xpathExpression;
private $predecessor;
/**
* Transform a DomDocument into a string.
* @param mixed $data
* @return string
*/
public function transform($data){
if($this->predecessor !== null){
$data = $this->predecessor->transform($data);
// At this point, we just have to "trust" that the predecessor returns a (DOMDocument)
}
$xpath = new DOMXpath($data);
$nodes = $xapth->query($this->xpathExpression);
if($nodes->length > 0){
throw new UnexpectedValueException("Xpath didn't match");
}
$result = $nodes->item(0)->nodeValue;
return $result;
}
}
用法:
$input = "..."
$xmlToDom = new XmlToDomDocumentAdapater();
$domToString = DomDocumentToStringAdapter();
$domToString->setPredecessorAdapter($xmlToDom);
$output = $domToString->transform($input);
当适配器依赖它的前任来返回正确的输入时,会出现问题部分。
if($this->predecessor !== null){
$data = $this->predecessor->transform($data);
// At this point, we just have to "trust" that the predecessor returns a (DOMDocument)
}
在C#中,我使用generics:
来解决这个问题interface AdapterInterface{
/**
* Tranform some input data into something else.
* @param mixed $data
* @return T
*/
public function T transform<T>(object data);
}
/* using it */
//...
if(this.predecessor !== null){
data = this.predecessor.transform<string>(data);
// we now know for sure that the data is of type 'string'
}
//...
由于PHP不支持泛型,我问自己在每次调用transform($data)
之后添加类型检查是否是一个好习惯:
if($this->predecessor !== null){
$data = $this->predecessor->transform($data);
if(!is_string($data){
throw new UnexpectedValueException("data is not a string!");
}
// we now know for sure that the data is of type 'string'
}
我目前正在使用多个接口来定义transform
方法的输出,如下所示:
interface ToStringAdapterInterface extends AdapterInterface{
/**
* Transform some input data into something else.
* @param mixed $data
* @return string <<< define expected output
*/
public function transform($data);
}
interface ToDomDocumentAdapterInterface extends AdapterInterface{
/**
* Transform some input data into something else.
* @param mixed $data
* @return DOMDocument<<< define expected output
*/
public function transform($data);
}
在每个变压器中,我确保只接受合适的接口作为前身:
class DomDocumentToStringAdapter implements ToStringAdapterInterface {
private $xpathExpression;
private $predecessor;
public function __construct(ToDomDocumentAdapterInterface $predecessor){
$this->predecessor = $predecessor;
}
// ...
}
答案 0 :(得分:0)
我会按照你的方法:测试$this->predecessor->transform($data)
的返回值数据类型,如果它不是预期的那样,则抛出异常。
我不知道您是否对Hack programming language by Facebook感兴趣:
Hack是HHVM的一种编程语言,可以无缝地互操作 用PHP。 Hack 协调PHP的快速开发周期 静态打字提供的纪律,同时添加了许多功能 常见于其他现代编程语言中。