Перегрузка функций — это механизм, который позволяет двум родственным функциям иметь одинаковые имена.
Допустим
Допустим необходимо реализовать функции, которые будут вычислить объем следующих фигур:
- куб
- шар
- цилиндр
- конус
- пирамида
- прямоугольный параллелепипед
// Объем куба
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
Автор: Lubaev