Hubbry Logo
search button
Sign in
Method chaining
Method chaining
Comunity Hub
History
arrow-down
starMore
arrow-down
bob

Bob

Have a question related to this hub?

bob

Alice

Got something to say related to this hub?
Share it here.

#general is a chat channel to discuss anything related to the hub.
Hubbry Logo
search button
Sign in
Method chaining
Community hub for the Wikipedia article
logoWikipedian hub
Welcome to the community hub built on top of the Method chaining Wikipedia article. Here, you can discuss, collect, and organize anything related to Method chaining. The purpose of the hub is to connect p...
Add your contribution
Method chaining

Method chaining is a common syntax for invoking multiple method calls in object-oriented programming languages. Each method returns an object, allowing the calls to be chained together in a single statement without requiring variables to store the intermediate results.[1]

Rationale

[edit]

Local variable declarations are syntactic sugar.[2]

Method chaining eliminates an extra variable for each intermediate step. The developer is saved from the cognitive burden of naming the variable and keeping the variable in mind.

Method chaining has been referred to as producing a "train wreck" due to the increase in the number of methods that come one after another in the same line that occurs as more methods are chained together.[3]

A similar syntax is method cascading, where after the method call the expression evaluates to the current object, not the return value of the method. Cascading can be implemented using method chaining by having the method return the current object itself. Cascading is a key technique in fluent interfaces, and since chaining is widely implemented in object-oriented languages while cascading isn't, this form of "cascading-by-chaining by returning this" is often referred to simply as "chaining". Both chaining and cascading come from the Smalltalk language.

While chaining is syntax, it has semantic consequences, namely that requires methods to return an object, and if implementing cascading via chaining, this must be the current object. This prevents the return value from being used for some other purpose, such as returning an error value.

Examples

[edit]

I/O streams

[edit]

A common example is std::istream and std::ostream (the input and output stream classes) in C++, where for example << returns the left object, allowing chaining.[4]

a << b << c;

// this is equivalent to:
a << b;
a << c;

Functional programming

[edit]

Functional programming is another example of the usage of method chaining, involving higher-order functions. In object-oriented programming, higher-order functions and manipulation of collections can be represented through methods that are chained together.[5]

One such example in Java uses the built-in methods of java.util.stream.Stream<E>:

import java.util.Arrays;
import java.util.List;
import java.util.streams.Collectors;

// ...

List<Integer> numbers = Arrays.asList(10, 25, 30, 45, 60, 75, 90);

List<Integer> result = numbers.stream() // .stream() returns java.util.stream.Stream
    .filter(n -> n > 30)
    .map(n -> n * 2)       
    .sorted()
    .collect(Collectors.toList());

Note that in Java, filter(), map(), and sorted() return a new shallow copy of the preceding list. However, to operate on the list in-place, the sort() method can be used.[6]

Language Integrated Query (or LINQ) for C# makes extensive usage of method chaining.[7]

using System;
using System.Collections;

// using method chaining:
IEnumerble<MyObject> results = SomeCollection
    .Where(c => c.SomeProperty < 10)
    .Select(c => new {c.SomeProperty, c.OtherProperty});

results.ForEach(x => {Console.WriteLine(x.ToString());})

// using LINQ keywords:
IEnumerable<MyObject> results = from c in SomeCollection
                                where c.SomeProperty < 10
                                select new {c.SomeProperty, c.OtherProperty};

foreach (MyObject result in results)
{
    Console.WriteLine(result);
}

C++20 introduces operator| (the piping operator) and allows LINQ-style chaining operations with the std::ranges namespaces. std::views contains several classes which are invoked through operator().[8]

using std::vector;
using std::ranges::to;
using std::views::filter;
using std::views::transform;

vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

// Pipeline: filter even numbers, double them, and then sum the result
vector<int> result = numbers
    | filter([](int n) -> bool { return n % 2 == 0; })
    | transform([](int n) -> int { return n * 2; })
    | to<vector>();

Design patterns

[edit]

The Builder pattern relies on constructing an object through method calls rather than immediately in its constructor. For example, java.lang.StringBuilder makes use method chaining to build a StringBuilder.[9]

StringBuilder sb = new StringBuilder();
String result = sb.append("Hello, ")
    .append("world!")
    .insert(0, "Greeting: ")
    .replace(10, 18, "beautiful ")
    .toString();

The Fluent interface pattern relies entirely on method chaining to implement method cascading.[10]

In C++, similar method chaining to Java and C# can be accomplished by having the methods return (for example, for a class StringBuilder, .append() and .replace() could have type StringBuilder& and return *this). However, in C++ it is important to be conscious of potential object slicing if the returned reference is to a parent class, while other languages such as Java, C#, and Rust are not subject to this problem.[11][12]

See also

[edit]

References

[edit]
  1. ^ "Applying Method Chaining". First Class Thoughts. Archived from the original on 2011-02-22. Retrieved 2011-04-13. In order to simplify repeated object interactions on the same object the old trick Method Chaining originating the world of Smalltalk should be enforced. The idea is to let methods return this rather than void, thus affecting especially set() and add() methods. Method chaining arose during the designers of Smalltalk pursuit to minimize the number of keywords in the language, which lead to the discovery that void is an unnecessary keyword!.
  2. ^ "CMSC 631 – Program Analysis and Understanding" (PDF). • Syntactic sugar for local declarations - let x = e1 in e2 is short for (λx.e2) e1
  3. ^ Martin, Robert Cecil (2008). Clean Code: A Handbook of Agile Software Craftsmanship. Prentice Hall. ISBN 978-0-13-235088-4.
  4. ^ "std::basic_ostream". cppreference.com. 4 September 2025.
  5. ^ Nakamaru, Tomoki; Matsunaga, Tomomasa; Yamazaki, Tetsuro; Akiyama, Soramichi; Chiba, Shigeru (2020). An Empirical Study of Method Chaining in Java. Seoul, Republic of Korea: Association for Computing Machinery. pp. 93–102. doi:10.1145/3379597.3387441. ISBN 9781450375177. Retrieved 2025-09-04. {{cite book}}: |website= ignored (help)
  6. ^ "Stream (Java SE)". docs.oracle.com. Retrieved 4 September 2025.
  7. ^ "Language Integrated Query (LINQ) - C# Microsoft Learn". learn.microsoft.com. Retrieved 4 September 2025.
  8. ^ "Ranges library (since C++20) - cppreference.com". cppreference.com. Retrieved 4 September 2025.
  9. ^ "StringBuilder (Java SE)". docs.oracle.com. Retrieved 4 September 2025.
  10. ^ Martin Fowler, "FluentInterface", 20 December 2005
  11. ^ R., Subburaj (2013). Object Oriented Programming with C++ ANSI /ISO Standard. Vikas Publishing House. p. 260-261. ISBN 978-93-259-6996-4.
  12. ^ Grimes, Richard (2017-04-24). Beginning C++ Programming. Birmingham: Packt Publishing Ltd. p. 309. ISBN 978-1-78712-928-3.
[edit]