html.okpython.net
HTML и CSS для начинающих

PHP :: Анонимные функции

Понятие анонимной функции

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

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

PHP Результат htmlCodes
<?php

//Выведет ошибку, т.к. анонимные функции определяются только в момент
//их первого использования, в отличие от именованных функций, которые
//доступны из любой точки программы, за исключением случаев, когда они,
//например, определены условно
//$my_func('test'); 

//Определяем анонимную функцию
$my_func = function($str){
   echo $str;
}; //Обязательно ставим точку с запятой    				 			

//Выведет строку 'test'
$my_func('test'); 

?>

Пример №1. Создание анонимных функций

Наследование переменных замыканиями, служебное слово use

Важной особенностью замыканий является то, что они могут наследовать переменные из родительской области видимости. Делается это при помощи служебного слова use (см. пример №2).

PHP Результат htmlCodes
<?php

//Создаем переменную в родительской области видимости
$str='test №1'; 	

//Наследуем внешнюю переменную
$my_func_1 = function() use ($str){  
   echo $str.'<br>';  
};    

//Выведет также строку 'test №1'
$my_func_1(); 		

//Изменяем переменную в родительской области видимости
$str='test №2'; 	

//Выведет унаследованное значение переменной $str, т.е.
//строку 'test №1', т.к. значение унаследованной переменной
//задается там, где функция определена, а не там, где вызвана!!!
$my_func_1();  	 	 


//Наследуем внешнюю переменную по ссылке						 
$my_func_2 = function() use (&$str){ 
   echo $str.'<br>';  
};

//Выведет строку 'test №2'    
$my_func_2($str);  

//Изменяем переменную в родительской области видимости			 
$str='test №3'; 	 						 
//Выведет строку 'test №3', т.к. переменная наследовалась по ссылке
$my_func_2();  	 	  


//Аргументы передаются обычным способом					 					 
$my_func_3 = function($str_1) use ($str){
   echo $str_1.$str.'<br>';  
}; 
   
//Создаем переменную в родительской области видимости
$str_1='Это '; 	 	 
//Выведет строку 'Это test №3'
$my_func_3($str_1);						 

?>

Пример №2. Наследование переменных замыканиями из родительской области видимости

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

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

PHP Результат htmlCodes
<?php

//Внешняя функция
function sale_func($price){ 							 
  	//Наследуем локальную переменную
	$start_price = function() use ($price){  
		//При использовании вернет начальное значение $price
		return $price; 
	}; 
	
	//Вычисляем 20% от начальной цены
	$price*=0.2; 		 
	//Получаем цену со скидкой
	$price=$start_price()-$price; 
	echo 'Цена со скидкой в 20% составит '.$price.' у.е.';
}    

//Выведет строку 'Цена со скидкой в 20% составит 40 у.е.'
sale_func(50);  	 

/* В примере замыкание использовалось в локальной области видимости, которая 
является для нее родительской областью видимости. При использовании же 
ключевого слова global, ссылка всегда ведет к переменной в глобальной
области видимости */

?>

Пример №3. Использование замыканий в локальной области видимости

Быстрый переход к другим страницам