Comments 51
Мне нравится ваш стиль изложения.
+9
Кстати, может кому-то будет полезно:
Я долго искал, как вызвать анонимное замыкание. function(){}() в php, ясен пень, не работает. Оказывается, можно сделать так:
$list = call_user_function(function($var) use ($lib) {
}, $myvar + 1);
Я долго искал, как вызвать анонимное замыкание. function(){}() в php, ясен пень, не работает. Оказывается, можно сделать так:
$list = call_user_function(function($var) use ($lib) {
}, $myvar + 1);
+1
Извините, а можно пару примеров, зачем вам это делать?
0
Для удобства. Например, на ходу преобразовать список, когда array_ функции не подходят (включая array_walk). Да много применений.
А зачем в javascript по-вашему так делают (например):
(function($){
}(jQuery));? (кстати, пример неудачный, но где-то близко)
А зачем в javascript по-вашему так делают (например):
(function($){
}(jQuery));? (кстати, пример неудачный, но где-то близко)
0
Это делают чтобы не засорять глобальную область видимости. А jQuery и $ там стоят для того, чтобы не было конфликта имён (если правильно помню). И то, и то нецелесообразно, в PHP есть неймспейсы, классы и функции, и анонимные функции.
Можно пример поудачнее?
Можно пример поудачнее?
+1
В JS не стоит лазить в глобальное пространство имён, так как на сайте скорее всего будут использоваться компоненты третьих лиц и могут возникнуть конфликты. Анонимные замыкания там используются лишь потому, что язык не поддерживает пространства имён.
В пхп анонимные замыкания не имеют смысла.
В пхп анонимные замыкания не имеют смысла.
+1
В php аномнимные замыкания можно использовать как раз для того, чтобы не засорять локальную область видимости.
-1
Если у вас локальная область настолько разрослась, то вам стоит лучше продумать структуру проекта. Это же сколько нужно напихать всего в один метод, чтобы начались конфликты?
0
Само собой, нужно.
Но когда нужно срочно что-то поправить, на рефакторинг время нет. Анонимные функции позволяют делать быстрые правки не засоряя проект лапшекодом. Собственно, вы разве не согласны, что это не так уж и плохо? Лучше люди будут использовать замыкания, чем пихать все в длиннющий скрипт.
Но когда нужно срочно что-то поправить, на рефакторинг время нет. Анонимные функции позволяют делать быстрые правки не засоряя проект лапшекодом. Собственно, вы разве не согласны, что это не так уж и плохо? Лучше люди будут использовать замыкания, чем пихать все в длиннющий скрипт.
0
Например, если бы вы хотели получить список только публичных переменных класса прямо из метода класса «в одну строку» без использования Reflection и тому подобной тяжелой артиллерии, вы могли пользоваться таким трюком в PHP 5.3.
0
Ключевое слово «в одну строку»?
+1
«В одну строку» я намеренно написал в кавычках, как вы можете видеть. Ключевое слово здесь «без использования Reflection». Например, в PHP 5.3 можно было сделать так:
В 5.4 такой трюк не работает и остаётся только:
call_user_func(function($object) {return get_object_vars($object);}, $this);
В 5.4 такой трюк не работает и остаётся только:
$reflection = new ReflectionObject($this);
foreach ($reflection->getProperties(ReflectionProperty::IS_PUBLIC) as $property) { //...
0
подробнее об анонимных функциях и замыканиях (en)
fabien.potencier.org/article/17/on-php-5-3-lambda-functions-and-closures
fabien.potencier.org/article/17/on-php-5-3-lambda-functions-and-closures
0
Картинка к посту намекает куда лучше с этим переходить? :)
+3
На мой взгляд, использование типажей (или сходных механизмов) более естественно в динамически типизированных языках, нежели танцы с интерфейсами и наследованием.Теперь осталось написать с десяток книг про ТОП(типажи-ориентированное-программирование), и подождать с десяток лет пока созреют хоть какие-то стандарты проектирования в этом стиле. А сама концепция мне чем-то напоминает инженерию генных модификаций: с одной стороны может быть очень круто, с другой стороны очень опасно.
+2
Ну, в принципе то, о чем я написал это не Rocket Science, и на откровение не претендует. Похожая концепция уже давно есть в Ruby, только называется по-другому (модули). Правда, на мой взгляд, у типажей перед модулями есть одно преимущество — можно явно объявить контракт.
Касательно стандартов проектирования это конечно вопрос открытый, но хорошие примеры использования можно найти в Ruby on Rails.
Касательно стандартов проектирования это конечно вопрос открытый, но хорошие примеры использования можно найти в Ruby on Rails.
0
Не вижу противоречий. Просто в Ruby примеси это, грубо говоря, модули; в PHP — это типажи. Однако примесь, это на мой взгляд, более широкое понятие, т.е., типажи это примеси, но не все примеси — типажи. Я же хотел привести наиболее конкретное и практичное сравнение.
0
UFO just landed and posted this here
Если подойти к вопросу строго, то трейты в PHP не охватывают полностью понятие «примесь». Трейт PHP это, скажем так, статическая примесь, которая применяется по отношению к классу. Но мы также можем реализовать механизм «подмешивания» по отношению к объектам, т.е. в рантайме, и тут тоже мы имеем дело с примесью, но это уже не будет трейт.
В целом, конечно, да: и трейты, и примеси, и модули — это об одном и том же, однако есть нюансы.
В целом, конечно, да: и трейты, и примеси, и модули — это об одном и том же, однако есть нюансы.
0
На русской википедии про трейты вообще бред написан.За чем же дело стало?
0
Что нам нужно от коллекции для того, чтобы мы могли реализовать эти методы? Только одно: мы должны иметь возможность итерироваться по элементам коллекции. Давайте назовем этот необходимый функционал контрактом.
А давайте не будем!
А давайте не будем!
0
Ну, можно и не называть. Однако называть все же удобнее, тогда текст читать проще ;) Если Вас конкретно слово «контракт» не устраивает, предложите более подходящую альтернативу.
+1
Давайте я не буду городить огород и Вы тоже, просто потому что для подобных вещей в программировании существует одно и ровно одно слово — интерфейс(я не про тот который с ключевым словом в php). А синонимы Вы ему подбирайте какие Вам нравятся — соглашение об использовании, контракт, реализация методов и т.п.
Не собираююсь ничего навязывать и доказывать, просто заметил что слово «контракт» и правда режет немного слух, хотя ничего критичного в его использовании нет.
Не собираююсь ничего навязывать и доказывать, просто заметил что слово «контракт» и правда режет немного слух, хотя ничего критичного в его использовании нет.
0
Возможно я немного запутанно написал, чем мог ввести в заблуждение. Так что постараюсь прояснить этот момент.
Интерфейс, по-сути, это публичная морда класса, или подсистемы, т.е., грубо говоря, набор методов, с которыми взаимодействует внешняя среда.
Термин "контракт" же я применяю по отношению к функционалу, который должен быть реализован в классе для того, чтобы иметь возможность включить определенный трейт, т.е. необходимый для его правильного функционирования.
Тут существует принципиальная разница! Несложно придумать пример когда пересечение интерфейса и контракта будет пусто.
Интерфейс, по-сути, это публичная морда класса, или подсистемы, т.е., грубо говоря, набор методов, с которыми взаимодействует внешняя среда.
Термин "контракт" же я применяю по отношению к функционалу, который должен быть реализован в классе для того, чтобы иметь возможность включить определенный трейт, т.е. необходимый для его правильного функционирования.
Тут существует принципиальная разница! Несложно придумать пример когда пересечение интерфейса и контракта будет пусто.
+1
Интерфейс описывает синтаксис, а контракт понятие более широкое, оно описывает и поведение как вызываемого, так и вызывающего кода.
0
Так то интересно, но постарайтесь брать более «живые» примеры.
+2
Раньше из букв P,H,P пытались выкладывать слово Java, нынче выкладывают слово Scala.
+3
Неплохо! :) Хотя, мне кажется, скорее не Scala, а Groovy.
-1
В Scala, кстати, traits сделаны существенно грамотней (благодаря наличию нормальной теоретической основы, например, линеаризации базовых типов). Там это полезный и продуманный инструмент, а не просто перетянутая модная фишечка. И авторы языка предлагают несколько действительно полезных применений: предоставление «толстых» интерфейсов без дубликации кода (на примере стандартного класса Comparable [ala Boost.Operators] и стандартных коллекций), реализация декораторов (очень удобная и полезная на практике), механизм compile-time dependency injection, также известный как Cake-pattern.
+1
Занятно! Слышал много хорошего (как и немного плохого) о Scala, но никак руки не доходили.
А касательно «модной фишечки», слышал в одном докладе занимательную аналогию: PHP — язык-пират, он крадет у других языков и присваивает себе. И смешно и грустно.
А касательно «модной фишечки», слышал в одном докладе занимательную аналогию: PHP — язык-пират, он крадет у других языков и присваивает себе. И смешно и грустно.
0
переложите в слове PHP 15 спичек так чтобы получилось… Вы об этом чтоли? Странно не это, странно то что многие еще и не справляются :)
+1
Господи, причем тут интерфейсы? Трейты и миксины решают проблему множественного наследия.
+2
решают? O RLY? Они грязно насилуют множественное наследование своим стеком объявлений вот и всё… Но ни разу не решают. Решали бы — в трейтах бы не было чудо-конструкций «а дайвайте сделает кроме s/p/p аксессоров еще и чудо-слова чтобы трейт типа перекрывал другой трейт»
-3
Не соглашусь с вами. Между трейтами и интерфейсами довольно тесная связь. Одна из довольно часто используемых возможностей трейтов — как раз предоставление «толстого» интерфейса, не требуя от программиста, использующего трейт, определения большого числа методов (в то время как простой интерфейс требует определения всех методов, в нём объявленных). Собственно, в статье автор использует как раз эту идиому и описывает одну миллиардную часть реализации Scala-коллекций. В них достаточно примиксовать Traversable и определить один метод foreach, остальные 100500 полезных методов получаются автоматом.
Да, это не единственная ситуация, когда треты полезны. Тем не менее, за PHP не скажу, а уж в Scala трейты «проблему» множественного наследованя точно не решают. Например, в Scala у трейтов не может быть конструкторов.
Да, это не единственная ситуация, когда треты полезны. Тем не менее, за PHP не скажу, а уж в Scala трейты «проблему» множественного наследованя точно не решают. Например, в Scala у трейтов не может быть конструкторов.
0
Интерфейсы помогают описать контракт взаимодействия, а трейты принести стандратную реализацию для интефейсов.
К примеру можно взять пары из ZF2
ServiceLocatorAwareInterface && ServiceLocatorAwareTrait
EventManagerAwareInterface && EventManagerAwareTrait
LoggerAwareInterface && LoggerAwareTrait
К примеру можно взять пары из ZF2
ServiceLocatorAwareInterface && ServiceLocatorAwareTrait
EventManagerAwareInterface && EventManagerAwareTrait
LoggerAwareInterface && LoggerAwareTrait
0
Единственный вопрос — как бы это дело подружить с IDE? В случае интерфейсов и классов — подсказки методов работают отлично. Но что если нам в коде нужен функционал двух и более типажей?
0
Я использую IntelliJ Idea с PHP плагином, так вот он отлично дружит с типажами.
0
Вы не совсем поняли проблему. Допустим есть
И есть некая функция вида
Вот каким образом в функции x IDE сможет понять, что у obj есть методы f и g. Если бы описание функции было вида
то все бы работало отлично. Но в случае с утиной типизацией — мы не можем указывать тип принимаемого объекта в функции
trait Foo {
public function f();
}
trait Bar {
public function g();
}
class A {
use Foo;
use Bar;
}
И есть некая функция вида
function x($obj) {
$obj->f();
$obj->g();
}
Вот каким образом в функции x IDE сможет понять, что у obj есть методы f и g. Если бы описание функции было вида
function x(A $obj) {
то все бы работало отлично. Но в случае с утиной типизацией — мы не можем указывать тип принимаемого объекта в функции
0
Впринципе подумал, что с помощью phpDoc это сделать, например
Но имхо это усложнит восприятие и не совсем верно с точки зрения семантики
/**
* @param Foo|Bar $obj
*/
function x($obj) {
}
Но имхо это усложнит восприятие и не совсем верно с точки зрения семантики
0
Статься интересная, но все же:
1. Зачем использовать трейты для таких элементарных задач, я все же не понял.
2. Вы объявляете функции с жестко заданым параметром \Closure. Это работает, но в контексте проектирования это не верно.
Так Вы сможете тыкать туда не только анонимные, но и типа: usort, array($object, 'methodName')
Ну и автору на заметку:
1. Использования в коде PHP 5.4 на данный момент не рекомендуеться, так как множество проектов просто не смогут заработать на ПХП 5.3 (К примеру: объявление массива [], использования трейтов).
2. Для получения массива с объекта, Вы используете toArray. Лучше унаследуйтесь от интерфейса IteratorAggregate
P.S.
В плане реализации этой задачи можно сразу использовать \Doctrine\Common\Collections\Collection :D
1. Зачем использовать трейты для таких элементарных задач, я все же не понял.
2. Вы объявляете функции с жестко заданым параметром \Closure. Это работает, но в контексте проектирования это не верно.
public function each($callback)
{
if (!is_callable($callback)) { throw new \InvalidArgumentException(); }
// ....
}
Так Вы сможете тыкать туда не только анонимные, но и типа: usort, array($object, 'methodName')
Ну и автору на заметку:
1. Использования в коде PHP 5.4 на данный момент не рекомендуеться, так как множество проектов просто не смогут заработать на ПХП 5.3 (К примеру: объявление массива [], использования трейтов).
2. Для получения массива с объекта, Вы используете toArray. Лучше унаследуйтесь от интерфейса IteratorAggregate
P.S.
В плане реализации этой задачи можно сразу использовать \Doctrine\Common\Collections\Collection :D
-1
Использование PHP 5.4 для того чтобы объявлять массивы вот так: [] не рекомендуется, а если уж нужны трейты, то лучше выбрать 5.4, а не отказываться от такого удобного инструмента.
0
Да, я с Вами вполне согласен! Я тоже иногда в проектах использую трейты, чтобы сократить время, но вот была на днях засада: Создал компонент, используя трейты, а в заказчика на хостинге PHP 5.3. Ну и на хостингах не везде можно попросить установить ПХП 5.4 (К примеру Mirohost). Вот и облажался.
Да и вот какие есть реальные задачи, где нужно использовать трейты (если говорить о проектировании системы)?
Почти все проблемы решаються выбором той или инной схемы патерна.
Да и вот какие есть реальные задачи, где нужно использовать трейты (если говорить о проектировании системы)?
Почти все проблемы решаються выбором той или инной схемы патерна.
0
2.
1. На носу выход 5.5 и, видимо, прекращение поддержки 5.3. Не, конечно, если делать движок, максимально совместимый со всем чем можно, то ориентироваться надо на 5.3, но если пишешь под более-менее контролируемую среду (заказчик возьмет хостинг какой скажешь) и/или долгоиграющий проект, то лучше на 5.4 ориентироваться. Вроде каждая мелочь в 5.4 погоды не делает, но вот в целом под 5.3 приходится себя заставлять писать чуть ли не с отвращением.
public function each(callable $callback)
{
// ...
}
1. На носу выход 5.5 и, видимо, прекращение поддержки 5.3. Не, конечно, если делать движок, максимально совместимый со всем чем можно, то ориентироваться надо на 5.3, но если пишешь под более-менее контролируемую среду (заказчик возьмет хостинг какой скажешь) и/или долгоиграющий проект, то лучше на 5.4 ориентироваться. Вроде каждая мелочь в 5.4 погоды не делает, но вот в целом под 5.3 приходится себя заставлять писать чуть ли не с отвращением.
0
Only those users with full accounts are able to leave comments. Log in, please.
Типажи и анонимные функции в PHP. Кря-кря!