Мне очень нравится философия цепочки методов, которую jQuery подчеркивает в своей библиотеке. Мне он показался довольно элегантным и понятным.
Будучи в первую очередь разработчиком Java, я всегда задавался вопросом, почему эта практика больше не использовалась в этом языке. Например, интерфейс Collection не был разработан таким образом (для добавления / удаления методов), и мне это показалось довольно печальным.
Есть ли у этой практики реальные минусы или это просто то, что раньше не имело достаточной "сексуальной привлекательности"?





Мне тоже очень нравится этот подход. Единственный недостаток, о котором я могу думать, это то, что иногда кажется немного неудобным «возвращать это» в конце каждого метода. Для JQuery, например, немного неудобно разрешать плагины, потому что вы должны сказать: «Убедитесь, что вы не забыли свои возвраты !!» но нет хорошего способа поймать это во время компиляции.
Единственный минус в том, что вы теряете возвращаемый тип, поэтому цепочка хороша для операций, которые что-то делают, но не подходят для операций, которые вычисляют вещи.
Другая проблема заключается в том, что с цепочкой компилятор не может так легко определять тривиальные вызовы функций для встраивания. Но, как я уже сказал, если ваша цепочка выполняет операции, а не вычисления, то, скорее всего, компилятор все равно ничего не изменит.
JavaScript - это (более или менее) функциональный язык с функциями первоклассного гражданина. Добавление / удаление методов к объектам, передача функций в качестве параметров, все это естественно для этого языка.
С другой стороны, Java строго объектно-ориентированный, функция не может существовать вне класса. Использование наследования, композиции и интерфейсов - более естественный способ для этого языка.
И? Какая связь между концепцией объектно-ориентированной / функциональной концепции и способом написания вызова метода? Действительно ли парадигма влияет на использование a.b (). C (), а не x = a.b (); x.c ()? Я так не думаю.
ой, извините, неправильный пример. Я хотел написать a.b (); a.c () конечно.
Ах, я думал о цепочке в смысле переопределения функции, а затем вызова старой функции в конце новой, например, когда всплывают события. Цепочка, описанная вами, действительно возможна в Java (и довольно часто), если функции возвращают правильный объект.
IMO болезненно отлаживать, поскольку у вас нет промежуточных переменных для проверки.
Насколько мне известно, все фактические IDE предоставляют функции пошагового входа / выхода, чтобы упростить отладку цепного метода, а также вызов метода, используемый в качестве параметров.
Цепные методы - еще один отличный инструмент в нашем наборе инструментов для дизайна. Только убедитесь, что вы не натолкнетесь на банальную фразу «У меня есть молоток, поэтому каждая проблема - гвоздь».
Не все проблемы дизайна решаются цепными методами. Иногда это действительно помогает упростить использование интерфейса (например, проблема сбора, о которой вы упомянули). Иногда это не так. Хитрость заключается в том, чтобы выяснить, какой случай применим.
Мартин Фаулер обсуждает эту тему как «свободные интерфейсы» на http://www.martinfowler.com/bliki/FluentInterface.html. Одна из основных проблем заключается в том, что плавные интерфейсы предназначены для людей, поэтому такие фреймворки, как Spring, не могут их понять. Упрощенно использование свободного интерфейса обеспечивает ремонтопригодность в одном смысле (удобочитаемость), но теряет ремонтопригодность в другом (гибкость).
Есть общая проблема с цепными методами и наследованием. Предположим, у вас есть класс C, чьи методы F1 (), F2 () и т. д. Возвращают C. Когда вы наследуете класс D от C, вы хотите, чтобы методы F1, F2 и т. д. Теперь возвращали D, чтобы цепочечные методы D могли быть вызванным в любом месте цепочки.
В C++ это обычно решается с помощью CRTP: en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern
Правда, к сожалению, универсальные шаблоны .NET не позволяют использовать параметры шаблона в спецификации базового класса для универсального класса. У Эрика Липперта в своем блоге (blogs.msdn.com/ericlipper) есть хорошее объяснение, почему это ограничение неизбежно в реализации дженериков .NET.
Если C# когда-либо будет поддерживать ковариантные возвращаемые типы, это может стать меньшей проблемой. Тем временем вы можете использовать ключевое слово new, чтобы скрыть базовые методы и заменить их версиями, использующими соответствующий тип возвращаемого значения. Я бы предложил в этих случаях вызвать базовый класс, чтобы избежать дублирования кода.
было бы хорошо, если бы в java была прагма, которая гласила: «вернуть это, если не было указано другое возвращаемое значение»? Или, что более вероятно, предупреждение компилятора.