Разработчику. Сборник рецептов PHP
Задавайте вопросы

Полиморфизм методов

Вернуться назад

Задача

Необходимо передать управление тому или иному коду в зависимости от количества и типа аргументов, переданных методу.

Решение

PHP не поддерживает полиморфизм методов в качестве встроенной функциональности. Однако можно его эмулировать посредством различных функций проверки типа. Следующая функция, combine(), использует функции is_numeric(), is_string(), is_array() и is_bool():

// функция combine() складывает числа, соединяет строки, объединяет массивы
// и выполняет операцию AND над битовыми и логическими аргументами
function combine($a, $b) {
     if (is_numeric($a) && is_numeric($b)) {
          return $a + $b;
}
     if (is_string($a) && is_string($b)) {
          return "$a$b";
     }

     if (is_array($a) && is_array($b)) {
          return array_merge($a, $b);
     }

     if (is_bool($a) && is_bool($b)) {
          return $a & $b;
     }
     return false;
}

Обсуждение

PHP не позволяет объявлять тип переменной в прототипе метода, поэтому он не может реализовать условное выполнение различных методов на основе их сигнатур, как это делается в Java и C++. Вместо этого можно написать одну функцию и использовать оператор switch, чтобы вручную восстановить эту функциональность.

Например, PHP позволяет редактировать образы с помощью GD. Удобно, если класс образа способен передать или местоположение образа (удаленное или локальное) или дескриптор, который PHP назначает существующему потоку образа. В примере, описанном ниже, показан класс pc_Image, который именно это и делает.

class pc_Image {

     var $handle;

     function ImageCreate($image) {
        if (is_string($image)) {
          // простое определение типа

          // путем захвата суффикса файла
          $info = pathinfo($image);
          $extension = strtolower($info['extension']);
          switch ($extension) {
          case 'jpg':
          case 'jpeg':
               this -> handle = ImageCreateFromJPEG($image);
break;
          case 'png':
               $this -> handle = ImageCreateFromPNG($image);
               break;
          default:
               die('Images must be JPEGs or PNGs.');
          }
     } elseif (is_resource($image)) {
          $this -> handle = $image;
     } else {
          die('Variables must be strings or resources.');
          }
     }
}

В данном случае любая переданная строка трактуется как путь к файлу, поэтому мы используем функцию pathinfo() для перехвата расширения файла. Как только расширение становится известным, мы пытаемся определить, какая из функций ImageCreateFrom() безошибочно открывает образ и создает дескриптор.

Если это не строка, то мы обращаемся непосредственно к потоку, который имеет тип resource. Поскольку нет необходимости проводить преобразование, мы присваиваем поток непосредственно переменной $handle. Естественно, применение этого класса при разработке программного обеспечения позволяет добиться более надежного определения и обработки ошибок.

Полиморфизм методов также позволяет вызывать методы с различным количеством аргументов. Код, который определяет количество аргументов внутри метода, идентичен тому, как происходит обработка функций с переменным количеством аргументов с помощью func_num_args().

См. также

Документация по функции is_string() на http://www.php.net/is-string, по функции is_resource() на http://www.php.net/is-resource и по функции pathinfo() на http://www.php.net/pathinfo.

Вернуться назад

Рейтинг@Mail.ru

Яндекс.Метрика

Индекс цитирования


Рейтинг Сайтов ДОСКИ.РУ