PHP_Over: имитатор перегрузок

от автора

image

Перегрузка функций — это механизм, который позволяет двум родственным функциям иметь одинаковые имена.

Допустим

Допустим необходимо реализовать функции, которые будут вычислить объем следующих фигур:

  • куб
  • шар
  • цилиндр
  • конус
  • пирамида
  • прямоугольный параллелепипед
// Объем куба function Volume_Cube(/*int*/ $side) {     return pow($side, 3); }  // Объем шара function Volume_Sphere(/*double*/ $radius) {     return ((4/3) * M_PI * pow($radius, 3)); }  // Объем цилиндра function Volume_Cylinder(/*double*/ $radius, /*int*/ $height) {     return (M_PI * pow($radius, 2) * $height); }  // Объем конуса function Volume_Сone(/*int*/ $height, /*double*/ $radius) {     return ((1/3) * M_PI * pow($radius, 2) * $height); }  // Объем пирамиды function Volume_Pyramid(/*int*/ $square, /*int*/ $height) {     return ((1/3) * $square * $height); }  // Объем прямоугольного параллелепипеда function Volume_Cuboid(/*int*/ $length, /*int*/ $width, /*int*/ $height) {     return ($length * $width * $height); } 

Это делает ситуацию сложнее, чем она есть на самом деле. Другими словами, при одних и тех же действиях (вычисление объема) программисту необходимо помнить имена всех шести функций вместо одного.

PHP_Over регистрирует значение, которое может быть вызвано как функция, по заданному количеству и/или значению типа аргумента, которое должно быть перегружено в процессе вызова.

require 'src/php_over/PHP_Over.php';  $Volume = new PHP_Over; $Volume     ->overload('%i',         function($side)     {         return pow($side, 3);     })     ->overload('%d',         function($radius)     {         return ((4 / 3) * M_PI * pow($radius, 3));     })     ->overload('%d', '%i',         function($radius, $height)     {         return (M_PI * pow($radius, 2) * $height);     })     ->overload('%i', '%d',         function($height, $radius)     {         return ((1 / 3) * M_PI * pow($radius, 2) * $height);     })     ->overload('%i', '%i',         function($square, $height)     {         return ((1 / 3) * $square * $height);     })     ->overload('%i', '%i', '%i',         function($length, $width, $height)     {         return ($length * $width * $height);     });  $Volume(5);        // 125 $Volume(5.);       // 523.5987755983 $Volume(3., 10);   // 282.74333882308 $Volume(10, 2.);   // 41.887902047864 $Volume(15, 9);    // 45 $Volume(15, 9, 3); // 405 

Теперь достаточно знать только одно имя $Volume, а для вычисления объема требуемой фигуры необходимо указать то количество и те типы аргументов, которые требуются.

Допустим

Допустим необходимо изменить набор фигур для которых требуется вычислить объем:

  • куб
  • шар
  • цилиндр
  • конус
  • пирамида
  • прямоугольный параллелепипед
  • правильный тетраэдр
  • призма
// ... Part 1  $Volume     ->override('%i',         function($edge)     {         return (pow($edge, 3) * sqrt(2) / 12);     })     ->override('%i', '%i',         function($square, $height)     {         return ($square * $height);     });  $Volume->invokeTo(5);        // 14.73139127472 $Volume->invokeTo(5.);       // 523.5987755983 $Volume->invokeTo(3., 10);   // 282.74333882308 $Volume->invokeTo(10, 2.);   // 41.887902047864 $Volume->invokeTo(15, 9);    // 135 $Volume->invokeTo(15, 9, 3); // 405 

Допустим

Допустим необходимо избавиться от некоторых перегружаемых функций, в процессе выполнения:

  • правильный тетраэдр
  • шар
  • цилиндр
  • конус
  • призма
  • прямоугольный параллелепипед
// ... Part 1 // ... Part 2  $Volume     ->override('%i', '%d')     ->override('%d', false);  function wrapperToVolume() {     global $Volume;      try {         return $Volume->invokeArgsTo(func_get_args());     } catch (Exception $exp) {         return $exp->getMessage();     } }  wrapperToVolume(5);         // 14.73139127472 wrapperToVolume(5.);        // Вызов неопределенной ранее функции wrapperToVolume(3., 10);    // Вызов неопределенной ранее функции wrapperToVolume(10, 2.);    // Вызов неопределенной ранее функции wrapperToVolume(15, 9);     // 135 wrapperToVolume(15, 9, 3);  // 405 


Скорость выполнения псевдо-перегружаемой функции, само собой, оставляет за собой право желать лучшего:

require 'src/php_over/PHP_Over.php';  define('NUMBER_OF_OPERATIONS_TEST_PHP_OVER', 1000000);  $array1 = array('a' => 'green', 'b' => 'brown', 'c' => 'blue', 'red'); $array2 = array('a' => 'green', 'b' => 'yellow', 'blue', 'red');  function my_array_intersect_assoc($array1, $array2) {     return array_intersect_assoc($array1, $array2); }  $php_over = new PHP_Over; $php_over->overload('%a', '%a', 'my_array_intersect_assoc');  function Test_1() {     global $array1, $array2;      $i = 0;     $t = microtime(true);     while ($i++ < NUMBER_OF_OPERATIONS_TEST_PHP_OVER) {         array_intersect_assoc($array1, $array2);     }      return (microtime(true) - $t); }  function Test_2() {     global $array1, $array2;      $i = 0;     $t = microtime(true);     while ($i++ < NUMBER_OF_OPERATIONS_TEST_PHP_OVER) {         my_array_intersect_assoc($array1, $array2);     }      return (microtime(true) - $t); }  function Test_3() {     global $php_over, $array1, $array2;      $i = 0;     $t = microtime(true);     while ($i++ < NUMBER_OF_OPERATIONS_TEST_PHP_OVER) {         $php_over->invokeTo($array1, $array2);     }      return (microtime(true) - $t); }  //========================================================================== //        | Count | PHP 5.3(average) | PHP 5.4(average) | PHP 5.5(average) | //========================================================================== // Test_1 |   5   |     6.56 sec     |     5.86 ses     |     5.69 sec     | //========================================================================== // Test_2 |   5   |    11.11 sec     |    10.02 sec     |     9.51 sec     | //========================================================================== // Test_3 |   5   |   148.6 sec      |   123.6 sec      |   115.4 sec      | //========================================================================== 


.git: PHP_Over

ссылка на оригинал статьи http://habrahabr.ru/post/211683/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *