Когда использовать цепочку
Цепочка функций в основном популярна в языках, где IDE с автозаполнением является обычным явлением. Например, почти все разработчики C # используют Visual Studio. Поэтому, если вы разрабатываете на C #, добавление цепочек к вашим методам может сэкономить время для пользователей этого класса, поскольку Visual Studio поможет вам в создании цепочки.
С другой стороны, такие языки, как PHP, которые по своей природе очень динамичны и часто не имеют поддержки автозаполнения в IDE, увидят меньше классов, поддерживающих сцепление. Цепочка будет уместна только тогда, когда правильные phpDocs используются для раскрытия цепочечных методов.
Что такое цепочка?
Для Foo
заданного класса следующие два метода являются цепочечными.
function what() { return this; }
function when() { return new Foo(this); }
Тот факт, что каждый является ссылкой на текущий экземпляр, а другой создает новый экземпляр, не меняет того, что это цепные методы.
Не существует золотого правила о том, что цепочечный метод должен ссылаться только на текущий объект. Infact, цепные методы могут быть в двух разных классах. Например;
class B { function When() { return true; } };
class A { function What() { return new B(); } };
var a = new A();
var x = a.What().When();
Нет ссылок ни this
в одном из приведенных выше примеров. Код a.What().When()
является примером цепочки. Интересно то, что тип класса B
никогда не присваивается переменной.
Метод сцепляется, когда его возвращаемое значение становится следующим компонентом выражения.
Вот еще один пример
// return value never assigned.
myFile.Open("something.txt").Write("stuff").Close();
// two chains used in expression
int x = a.X().Y() * b.X().Y();
// a chain that creates new strings
string name = str.Substring(1,10).Trim().ToUpperCase();
Когда использовать this
иnew(this)
Строки в большинстве языков неизменны. Поэтому вызовы метода цепочки всегда приводят к созданию новых строк. Где как объект типа StringBuilder может быть изменен.
Последовательность - лучшая практика.
Если у вас есть методы, которые изменяют состояние объекта и возвращают его this
, не смешивайте методы, которые возвращают новые экземпляры. Вместо этого создайте определенный метод с именем, Clone()
который будет делать это явно.
var x = a.Foo().Boo().Clone().Foo();
Это намного яснее относительно того, что происходит внутри a
.
Шаг снаружи и назад трюк
Я называю это уловкой шага назад и назад , потому что это решает много общих проблем, связанных с цепочкой. По сути, это означает, что вы выходите из исходного класса в новый временный класс, а затем возвращаетесь к исходному классу.
Временный класс существует только для предоставления специальных функций исходному классу, но только в особых условиях.
Часто цепочке необходимо изменить состояние , но класс A
не может представлять все эти возможные состояния . Таким образом, во время цепочки вводится новый класс, который содержит ссылку на A
. Это позволяет программисту перейти в состояние и вернуться в A
.
Вот мой пример, пусть специальное состояние будет известно как B
.
class A {
function Foo() { return this; }
function Boo() { return this; }
function Change() return new B(this); }
}
class B {
var _a;
function (A) { _a = A; }
function What() { return this; }
function When() { return this; }
function End() { return _a; }
}
var a = new A();
a.Foo().Change().What().When().End().Boo();
Это очень простой пример. Если вы хотите иметь больше контроля, то B
можете вернуться к новому супертипу A
с другими методами.
return this
. Как я могу помочь пользователям моих библиотек разобраться и понять эту ситуацию? (Позволить им связывать методы, даже если это не требуется, будет ли это действительно хорошо? Или я должен придерживаться только одного способа, требующего изменения вообще?)В зависимости от языка наличие методов, которые возвращают
void
/unit
и изменяют их экземпляр или параметры, не является идиоматическим. Даже в языках, которые раньше делали это больше (C #, C ++), это выходит из моды с переходом к программированию более функциональных стилей (неизменяемые объекты, чистые функции). Но давайте предположим, что сейчас есть веская причина.Для определенного поведения (думаю
x++
) ожидается, что операция возвращает результат, даже если она изменяет переменную. Но это во многом единственная причина сделать это самостоятельно.Это зависит.
В тех языках, где copy / new и return распространены (C # LINQ и строки), возврат одной и той же ссылки может привести к путанице. В тех языках, где модификация и возврат распространены (некоторые библиотеки C ++), копирование может привести к путанице.
Делать подпись однозначной (возвращая
void
или используя языковые конструкции, такие как свойства) было бы лучшим способом прояснить. После этого сделать имя понятным,SetFoo
чтобы показать, что вы модифицируете существующий экземпляр - это хорошо. Но ключ в том, чтобы поддерживать идиомы языка / библиотеки, с которой вы работаете.источник
Clear()
илиAdd()
любого типа коллекции, изменят тот же экземпляр и вернутсяvoid
. В обоих случаях вы говорите, что это будет сбивать с толку ...obj = myCollection.Where(x => x.MyProperty > 0).OrderBy(x => x.MyProperty);
тогда?Where()
возвращает новый объект коллекции.OrderBy()
даже возвращает другой объект коллекции, потому что содержимое упорядочено.IEnumerable
, но ясно, что они не являются копиями, и они не являются коллекциями (за исключениемToList
,ToArray
и т.д.).ICollection
. Виноват.(Я принял C ++ в качестве вашего языка программирования)
Для меня это в основном удобочитаемость. Если A, B, C являются модификаторами, особенно если это временный объект, передаваемый в качестве параметра какой-либо функции, например
по сравнению с
Повторная оценка, если все в порядке, чтобы вернуть ссылку на измененный экземпляр, я бы сказал «да» и указал, например, на потоковые операторы «>>» и «<<» ( http://www.cprogramming.com/tutorial/ operator_overloading.html )
источник
Вы также можете сделать цепочку методов с копией return вместо модификации return.
Хорошим примером на C # является string.Replace (a, b), который не меняет строку, к которой он был вызван, а вместо этого возвращает новую строку, позволяющую вам весело отделяться друг от друга.
источник