PHP ООП: уникальный метод для каждого типа аргумента? - PullRequest
3 голосов
/ 07 мая 2010

Я пишу немного доморощенного 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 - я хочу объявить переменную @param в Docblock. Лучше ли иметь уникальный метод для каждого типа аргумента или приемлемо иметь метод, который делегирует правильный внутренний метод / класс на основе типа аргумента?

Ответы [ 3 ]

6 голосов
/ 07 мая 2010

Допустимо иметь метод, который делегирует правильный внутренний метод. Вы можете задокументировать это так:

@param Array|User|Integer $argName optional explanation

но опять же, никто не мешает вам использовать один метод каждый

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

Кроме того, вы можете использовать magic __call метод , чтобы притвориться, что вышеупомянутые методы существуют, а затем перехватить вызовы методов для них и делегировать свои внутренние методы ( ZF выполняет эту функцию для поиска зависимые строки базы данных ). Вы должны документировать эти методы с помощью аннотации @method в классе DocBlock. Но имейте в виду, что магические методы всегда медленнее, чем непосредственно и / или вызывая соответствующие методы.

Используйте то, что, по вашему мнению, наиболее целесообразно для вашего приложения и варианта использования.

1 голос
/ 07 мая 2010

Вы можете достичь чего-то вроде перегрузки метода , проверив тип переданного параметра во время выполнения (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
    }
}
[...]
1 голос
/ 07 мая 2010

Это звучит , как будто вы хотите выполнить перегрузку функций, но PHP (даже PHP5) не выполняет перегрузку, как в случае с Java. Перегрузочная секция в руководстве по PHP не является функцией перегрузки :

Примечание: интерпретация 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) { ... }
}

Кажется, это хороший способ сделать это на мой взгляд.

...