Это работает для меня: предположим, что у меня есть эта зависимость
<dependency>
<groupId>com.company.app</groupId>
<artifactId>my-library</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/my-library.jar</systemPath>
</dependency>
Затем добавьте путь к вашей системной зависимости вручную, как это
<Class-Path>libs/my-library-1.0.jar</Class-Path>
Full config:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifestEntries>
<Build-Jdk>${jdk.version}</Build-Jdk>
<Implementation-Title>${project.name}</Implementation-Title>
<Implementation-Version>${project.version}</Implementation-Version>
<Specification-Title>${project.name} Library</Specification-Title>
<Specification-Version>${project.version}</Specification-Version>
<Class-Path>libs/my-library-1.0.jar</Class-Path>
</manifestEntries>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.company.app.MainClass</mainClass>
<classpathPrefix>libs/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/libs/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Вот как PHP выражает закрытие . Это вовсе не зло, и на самом деле это довольно сильно и полезно.
В основном это означает, что вы позволяете анонимной функции «захватывать» локальные переменные (в данном случае, $tax
и ссылку на $total
) вне ее области действия и сохранять их значения (или в случае $total
ссылка на сам $total
) как состояние внутри самой анонимной функции.
До самых последних лет PHP определял свой AST, а интерпретатор PHP изолировал синтаксический анализатор от части оценки. В то время, когда вводится замыкание, синтаксический анализатор PHP тесно связан с оценкой.
Поэтому, когда замыкание было впервые введено в PHP, у интерпретатора нет способа узнать, какие переменные будут использоваться в замыкании, потому что оно еще не проанализировано. Таким образом, пользователь должен порадовать движок Zend явным импортом, выполняя домашнюю работу, которую должен сделать Zend.
Это так называемый простой способ в PHP.
Зупа проделал большую работу, объясняя замыкания с помощью «использования» и разницы между «Ранним связыванием» и «Ссылкой на переменные, которые« используются ».
Итак, я сделал пример кода с ранним связыванием переменной (= копирование):
<?php
$a = 1;
$b = 2;
$closureExampleEarlyBinding = function() use ($a, $b){
$a++;
$b++;
echo "Inside \$closureExampleEarlyBinding() \$a = ".$a."<br />";
echo "Inside \$closureExampleEarlyBinding() \$b = ".$b."<br />";
};
echo "Before executing \$closureExampleEarlyBinding() \$a = ".$a."<br />";
echo "Before executing \$closureExampleEarlyBinding() \$b = ".$b."<br />";
$closureExampleEarlyBinding();
echo "After executing \$closureExampleEarlyBinding() \$a = ".$a."<br />";
echo "After executing \$closureExampleEarlyBinding() \$b = ".$b."<br />";
/* this will output:
Before executing $closureExampleEarlyBinding() $a = 1
Before executing $closureExampleEarlyBinding() $b = 2
Inside $closureExampleEarlyBinding() $a = 2
Inside $closureExampleEarlyBinding() $b = 3
After executing $closureExampleEarlyBinding() $a = 1
After executing $closureExampleEarlyBinding() $b = 2
*/
?>
Пример со ссылкой на переменную (обратите внимание на символ & amp; перед переменной); 114]
<?php
$a = 1;
$b = 2;
$closureExampleReferencing = function() use (&$a, &$b){
$a++;
$b++;
echo "Inside \$closureExampleReferencing() \$a = ".$a."<br />";
echo "Inside \$closureExampleReferencing() \$b = ".$b."<br />";
};
echo "Before executing \$closureExampleReferencing() \$a = ".$a."<br />";
echo "Before executing \$closureExampleReferencing() \$b = ".$b."<br />";
$closureExampleReferencing();
echo "After executing \$closureExampleReferencing() \$a = ".$a."<br />";
echo "After executing \$closureExampleReferencing() \$b = ".$b."<br />";
/* this will output:
Before executing $closureExampleReferencing() $a = 1
Before executing $closureExampleReferencing() $b = 2
Inside $closureExampleReferencing() $a = 2
Inside $closureExampleReferencing() $b = 3
After executing $closureExampleReferencing() $a = 2
After executing $closureExampleReferencing() $b = 3
*/
?>
function () use () {}
похоже на закрытие для PHP.
Без use
функция не может получить доступ к родительской переменной области действия
$s = "hello";
$f = function () {
echo $s;
};
$f(); // Notice: Undefined variable: s
$s = "hello";
$f = function () use ($s) {
echo $s;
};
$f(); // hello
Значение переменной use
берется из определения функции, а не при ее вызове
$s = "hello";
$f = function () use ($s) {
echo $s;
};
$obj = "how are you?";
$f(); // hello
use
переменная по ссылке с &
$s = "hello";
$f = function () use (&$s) {
echo $s;
};
$s = "how are you?";
$f(); // how are you?
крышки прекрасны! они решают множество проблем, связанных с анонимными функциями, и делают возможным действительно элегантный код (по крайней мере, пока мы говорим о php).
Программисты javascript постоянно используют замыкания, иногда даже не подозревая об этом, потому что связанные переменные не определены явно - вот для чего «использование» в php.
Есть лучшие примеры из реальной жизни, чем приведенный выше. Допустим, вам нужно отсортировать многомерный массив по подзначению, но ключ меняется.
<?php
function generateComparisonFunctionForKey($key) {
return function ($left, $right) use ($key) {
if ($left[$key] == $right[$key])
return 0;
else
return ($left[$key] < $right[$key]) ? -1 : 1;
};
}
$myArray = array(
array('name' => 'Alex', 'age' => 70),
array('name' => 'Enrico', 'age' => 25)
);
$sortByName = generateComparisonFunctionForKey('name');
$sortByAge = generateComparisonFunctionForKey('age');
usort($myArray, $sortByName);
usort($myArray, $sortByAge);
?>
предупреждение: непроверенный код (у меня не установлен php5.3 atm), но он должен выглядеть примерно так.
есть один недостаток: многие php-разработчики могут оказаться немного беспомощными, если вы столкнетесь с ними замыканиями.
Чтобы лучше понять замыкания замыканий, я приведу еще один пример - на этот раз в javascript. Одной из проблем является асинхронность, присущая браузеру. особенно, если речь идет о window.setTimeout();
(или -interval). Итак, вы передаете функцию в setTimeout, но вы не можете дать какие-либо параметры, потому что предоставление параметров выполняет код!
function getFunctionTextInASecond(value) {
return function () {
document.getElementsByName('body')[0].innerHTML = value; // "value" is the bound variable!
}
}
var textToDisplay = prompt('text to show in a second', 'foo bar');
// this returns a function that sets the bodys innerHTML to the prompted value
var myFunction = getFunctionTextInASecond(textToDisplay);
window.setTimeout(myFunction, 1000);
myFunction возвращает функцию с неким предопределенным параметром!
Если честно, мне больше нравится php с 5.3 и анонимные функции / замыкания. пространства имен могут быть более важными, , но они намного менее сексуальны .
Более простой ответ.
function ($quantity) use ($tax, &$total) { .. };
$tax
внутри замыкания не имеет внешнего эффекта, если только он не является указателем, как объект. &$total
. Таким образом, изменение значения $total
оказывает внешнее воздействие, значение исходной переменной изменяется. Как отметил @Mytskine , вероятно, лучшим подробным объяснением является RFC для замыканий . (Проголосуйте за него.)