Method chaining in Java - what is it, and what is it eaten with?


Explain how it lives and how to work with it?

The following phenomenon is meant:

Strings
    .emptyToNull(sector))
    .stream()
    .map(ClientCompany::fromCompany)
    .collect(Collectors.toList());
Author: LEQADA, 2015-12-02

4 answers

Quote from Wikipedia article Method chaining

Method chainig ( chains) - the general name of the syntax in OOP, in which several methods are called one after the other.

There's also a simple Java code example:

class Person {
  private String name;
  private int age;


  public Person setName(String name) {
      this.name = name;
      return this; // Возвращаем объект
  }

  public Person setAge(int age) {
      this.age = age;
      return this; // Возвращаем объект
  }

  public void introduce() {
      System.out.println("Hello, my name is " + name + " and I am " + age + " years old.");
  }

  // Использование:
  public static void main(String[] args) {
      Person person = new Person();
      // Output: Hello, my name is Peter and I am 21 years old.
      person.setName("Peter")
            .setAge(21)
            .introduce(); // Вызываем методы цепочкой (Method chaining)
  }
}

The whole idea is to make the methods called one after the other. To do this, each previous method must return the value that the next one needs. Like a Lego set.

The structure can be made very different, up to nested classes.

It can be highlighted that using this syntax saves time. I don't think it's worth using often. Such classes become unreadable as their complexity increases.

It is worth using only when it is very long without it.

 11
Author: LEQADA, 2015-12-02 15:54:20

In Java, it is no different from other programming languages. The whole idea of method chaining boils down to a simple rule:

Methods must return objects.

These can be absolutely any objects-either related to the class or the parents of the class containing the method, or not. Just always return the object when you exit the method.

If you apply this rule , you will be able to organize quite pleasant-looking chains of operations, like this one:

player
    .takeRevolver()
    .loadBullet()
    .rotateCylinder()
    .putToHead()
    .shoot();

Instead of subjectively less pleasant:

Revolver revolver = new Revolver(player);
revolver.loadBullet();
revolver.rotateCylinder();
revolver.putToHead();
revolver.shoot();

Also based on the idea of method chaining, there is the idea of a fluent interface, the essence of which is reduced to:

Methods must return the object they refer to.

This allows you to create quite pleasant-looking program interfaces for "builders", which involve multi-step configuration of the created objects:

Car car = CarBuilder:create()
    .setEngine(new Engine(FuelType::GAZOLINE, 1.5))
    .setExterior(Colors::BLACK_MATTE)
    .setInterior(Materials::GRAY_FABRIC)
    .setAbs(new Abs(4, 4))
    .setNeon(Colors::PURPLE)
    .build()
 8
Author: Sergey Rufanov, 2015-12-02 16:08:07

On habre, in my opinion, there is a good article on this topic. True, there is considered its implementation in C++, but as far as I understand, this technique is also applicable to java. Also, the link from @LEQADA to the English-language article in Wikipedia is present, it is a pity that there is no Russian

 0
Author: abbath0767, 2015-12-02 15:08:54

In addition to the advantages of "method chaining", there are also disadvantages. The code will not always look clear enough to understand in the inheritance hierarchy. Here is an example:

package chain;


class A {

public A chainedMethod() {
    System.out.println("  chainedMethod() in class A");
    return this;
}
}

class B extends A {

@Override
public A chainedMethod() {
    System.out.println("  chainedMethod() in class B");
    return this;
}

public void doStuff() {
    System.out.println("  doStuff() in B");
}
}

public class D extends B {

public static void main(String[] args) {
    //  (new B().chainedMethod()).doStuff();// ошибка - здесь попытка вызвать метод 
 //класса A
    ((B) new B().chainedMethod()).doStuff(); // так работает
}
}

That is, the code will not work without an explicit type cast. Additional type casts will make the code difficult to read.

 0
Author: Vyacheslav Mishchenko, 2019-10-02 10:05:11