PHP OOP:每个参数类型的唯一方法?

Posted

技术标签:

【中文标题】PHP OOP:每个参数类型的唯一方法?【英文标题】:PHP OOP: Unique method per argument type? 【发布时间】:2010-05-07 14:40:04 【问题描述】:

我正在编写一些自制的 ORM(学术兴趣)。我正在尝试将 TDD 概念作为一项培训练习,并且作为该练习的一部分,我在开发课程时正在为 API 编写文档。

举个例子——我正在研究一个经典的“getCollection”类型映射器类。我希望它能够为特定用户检索资产 X 的集合(比如说博客文章),以及基于任意数值数组的集合。所以 - 你可能有一个像这些中的任何一个的方法

$User = $UserMapper->load(1);
$ArticleCollection = $ArticleMapper->getCollection(range(10,20));
$ArticleCollection = $ArticleMapper->getCollection($User);
$ArticleCollection = $ArticleMapper->getCollection($User->getId());

因此,在编写 getCollection 方法的文档时 - 我想在 Docblock 中声明 @param 变量。是为每种参数类型设置一个唯一的方法更好,还是根据参数类型委托给正确的内部方法/类的方法是否可以接受?

【问题讨论】:

【参考方案1】:

拥有一个委托给正确内部方法的方法是可以接受的。你可以像这样记录它:

@param Array|User|Integer $argName optional explanation

但话又说回来,没有人会阻止你每个人都有一种方法

public function getCollectionByRange(array $range)
public function getCollectionByUser(User $user)
public function getCollectionByUserId($id)

此外,您可以使用magic __call method 假装上述方法存在,然后捕获对它们的方法调用并委托给您的内部方法(ZF does that f.i. for finding dependant database rows)。您将在 Class DocBlock 中使用 @method 注释记录这些方法。但请记住,魔术方法总是比直接拥有和/或调用适当的方法慢。

使用您认为对您的应用程序和用例最有意义的内容。

【讨论】:

【参考方案2】:

您可以通过在运行时检查传递参数的类型来实现类似method overloading 的功能(php 不支持从其他语言(例如 ADA、Java、C# 或 C++ 等)已知的这一概念):

[...]
/**
 * @param  User|array|integer $user
 * @return array
 */
public function getCollection($user) 
    // perhaps a switch-case would be better here
    if ($user instanceof User) 
        // do what has to be done if you passed in a User object
     else if (is_int($user) 
        // do what has to be done if you passed in a user id
     else if (is_array($user)) 
        // do what has to be done if you passed in an array of user ids
    

[...]

【讨论】:

感谢您的回答 - 但是,我对如何做,而不是为什么(或什么被认为是“最佳实践”)不太感兴趣 “使用你认为对你的应用程序和用例最有意义的东西。” - 我想 Gordon 是在 26 分钟前添加的。在大多数情况下,我认为没有最佳方法:这取决于。我个人会选择一种方法,因为它使 API 保持整洁。【参考方案3】:

听起来就像你想做函数重载,但是 PHP(甚至 PHP5)不像你在 Java 中那样做重载。 PHP手册中的Overloading section不是function overloading:

注意:PHP的解释 “重载”与大多数不同 面向对象的语言。重载 传统上提供的能力 有多个相同的方法 名称,但不同的数量和 参数类型。

你可能是这个意思:

class ArticleMapper 
   public function getCollection($param) 
      if (is_array($param))  $this->getCollectionByArray($param); 
      if (is_int($param))  $this->getCollectionByInt($param); 
      if (is_a($param, 'User'))  $this->getCollectionByUser($param); 
   
   private function getCollectionByArray(array $param)  ... 
   private function getCollectionByInt($param)  ... 
   private function getCollectionByUser(User $param)  ... 

在我看来,这似乎是个不错的方法。

【讨论】:

谢谢,感谢您的回答,并且非常接近我的初始实施。我很想知道的是,从 OOP 最佳实践的角度来看,使用独特的方法 re: 责任是否更好? 啊,好点子:php.net/manual/en/language.oop5.typehinting.php 我会从我的回答中删除那个错误的int

以上是关于PHP OOP:每个参数类型的唯一方法?的主要内容,如果未能解决你的问题,请参考以下文章

java第六课 oop

关于PHP的方法参数类型约束

OOP 实例方法封装与使用

带有 lambda 作为每个实例化的唯一默认参数的模板

Java中方法的重载与重写

Java中方法的重载与重写