2013-08-08 2 views
2

У меня есть простой пример:php Закрытие: что делать дальше?

function func1(){ 
    return function(){ 
     return 1; 
    }; 
} 

, но это не ясно для меня, как я могу использовать это для моего разума. Кажется, что func1() возвращает то же самое, что и анонимная функция. Но если я пишу так:

echo func1(); 

... Я получаю сообщение об ошибке:

Catchable fatal error: Object of class Closure could not be converted to string in [file_name] on line [line] 

Я не могу получить ничего, кроме закрывающего объекта:

var_dump(func1()); 
--------------------- 
object(Closure)[1] 

однако я не могу см. практическое использование этого. Он всегда содержит один и тот же объект независимо от того, что возвращает анонимная функция - object (Closure) [1]. (я использую php 5.3.3) Также я не вижу способа сохранить значение, возвращаемое анонимной функцией внутри func1(). Как я вижу, это все-таки закрывающий объект. Но как использовать его там и за его пределами?

+4

* Этот * не очень полезен, но другие могут быть: 'function make_adder ($ x) {return function ($ y) use ($ x) {return $ x + $ y; }} 'позволяет вам делать что-то вроде' $ adder = make_adder (3); echo $ сумматор (2); // печатает 5'. –

+1

Вышеприведенный пример может использоваться для [currying] (http://stackoverflow.com/questions/36314/what-is-currying) функций, что исключительно полезно. – Orbling

+1

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

ответ

4

В вашем примере возвращаемое значение вызова func1 является функцией (точнее, Closure). Ошибка, которую вы получаете, связана с тем, что php не может преобразовать этот объект в строку. Если вы хотите напечатать значение, возвращаемое закрытием, вам нужно вызвать его.

function func1() { 
    return function() { 
     return 1; 
    }; 
} 

$f = func1(); // Create the closure 
echo $f(); // Calls the closure 

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

Рассмотрим этот тривиальный пример:

function multiplier($m) { 
    return function ($v) use ($m) { 
     return $v * $m; 
    }; 
} 

$mult_5 = multiplier(5); 
echo $mult_5(5); // prints 25 

$mult_10 = multiplier(10); 
echo $mult_10(5); // prints 50 

Опять же, это очень тривиальный пример, но демонстрирует несколько важных вещей. Во-первых, мы определили только одну функцию, но, вызвав эту функцию, смогли сгенерировать две аналогичные, но разные функции, просто изменив параметры, когда мы их вызвали. Также учтите, что каждая функция имеет свое «состояние». В случае функции, которую я назвал $mult_5, она знает, что ее собственное внутреннее значение $m составляет 5, и это отличается от значения $m функции $mult_10. Значение для каждого из них было передано функции multiplier, и эта функция завершилась, но значение сохраняется в возвращаемой функции/закрытии.

Стоит также отметить, что каждое возвращаемое значение вызова multiplier является первой функцией класса, а это означает, что вы можете написать обобщенные функции (например, multiplier), а затем использовать их для создания более конкретных функций «на лету» , функции, которые более конкретно подходят для текущей среды/состояния вашей программы.

Если вы знакомы с объектно-ориентированным программированием, приведенный выше пример может быть легко переписан с использованием ООП:

class Multiplier { 

     protected $m; 

     public function __construct($m) { 
       $this->m = $m; 
     } 

     public function multiply($v) { 
       return $v * $this->m; 
     } 
} 

$mult_5 = new Multiplier(5); 
echo $mult_5->multiply(5); // prints 25 

$mult_10 = new Multiplier(10); 
echo $mult_10->multiply(5); // prints 50 

... и это очень субъективно, но я предпочитаю более consice синтаксис закрытие.

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

function multiplier($a, $b) { 
    return $a * $b; 
} 

echo multiplier(5, 5); 
echo multiplier(5, 10); 

Но выгода от использования закрытия вместо является то, что вы можете скрыть данные (например, мультипликатора, в данном примере).

+0

Спасибо, Карл за блестящий ответ! :) Это действительно заполнило пробел в моем понимании предмета. Теперь я читаю довольно хорошую книгу (которая называется Php.Pro.Programming), но этот момент объяснялся там довольно бедно :(Может быть, вы знаете какую-нибудь книгу лучше? – srgg6701

1

Анонимные функции становятся полезными, когда вы используете их в качестве параметров для таких функций, как array_filter(). See here documentation here.

Кроме того, попытались сделать это:

$x = func1(); 
echo $x(); 

Если так что вы будете результаты этого зависит от того, как вы определяете func1.

+0

Я думаю, он спрашивает, что такое практическое использование закрытий, но он не применяет закрытие правильно. – Strawberry

+0

Если честно, у меня нет степени Comp Sci и поэтому я не понимаю закрытия, но я все еще могу использовать их для использования их для множества полезных вещей на PHP и с помощью jQuery. – Annabel

Смежные вопросы