Home > Mobile >  Java Structured Method Chaining
Java Structured Method Chaining

Time:07-30

A bit of a question on working with objects in java. Suppose I have the following class.

public class Example {

    private String ex1 = new String();
    private String ex2 = new String();
    private int varOne;

    public Example logicOne(/*Input variables*/) {
        // Do logic
        return this;
    }

    public Example logicTwo(/*Input variables*/) {
        // Do logic
        return this;
    }

    public int subLogicOne(/*Input variables*/) {
        return varOne;
    }

    public int subLogicTwo(/*Input variables*/) {
        return varTwo;
    }

    public int subLogicThree(/*Input variables*/) {
        return varThree;
    }
}

I know that setting a methods type to the class name and using return this will allow me to chain methods when calling the class object like so.

Example obj = new Example;
obj.logicOne("inputOne").logicTwo("inputTwo");

But how would I restrict which methods could be called? For example making logicOne and logicTwo mutually exclusive and restricting subLogicOne to logicOne and subLogicTwo to logicTwo with subLogicThree being shared between them like this.

Example obj = new Example;

obj.logicOne("inputOne").subLogicOne("subInputOne");
obj.logicTwo("inputTwo").subLogicTwo("subInputTwo");

obj.logicOne("inputOne").subLogicThree("subInputThree");
obj.logicTwo("inputTwo").subLogicThree("subInputThree");

CodePudding user response:

You can use interfaces to divide up the methods.

// you can probably come up with better names, taking your real situation into account
interface Logicable {
    SubLogicOneAble logicOne(/*same input variables as logicOne*/);
    SubLogicTwoAble logicTwo(/*same input variables as logicTwo*/);
}

interface SubLogicThreeAble {
    int subLogicThree(/*same input variables as subLogicThree*/);
}

interface SubLogicOneAble extends SubLogicThreeAble {
    int subLogicOne(/*same input variables as subLogicOne*/);
}

interface SubLogicTwoAble extends SubLogicThreeAble {
    int subLogicTwo(/*same input variables as subLogicTwo*/);
}

Then, you can let callers create instances of Example via a factory method that returns Logicable, rather than new Example(). This way, the first methods that callers can call are only logicOne and logicTwo, unless they explicitly cast to Example, of course.

class Example implements SubLogicOneAble, SubLogicTwoAble, Logicable {
    private Example() {}

    // could also consider putting this in Logicable and calling it newLogicable (?)
    public static Logicable newExample() {
        return new Example();
    }
Example.newExample().subLogicOne() // compiler error

Notice also that I changed logicOne and logicTwo to return SubLogicOneAble and SubLogicTwoAble respectively. This is to ensure that callers can only call certain methods on the return values of those methods (again, unless they explicitly cast). The signatures in Example should be changed to agree with the interfaces:

public SubLogicOneAble logicOne (/*Input variables*/){
    // Do logic
    return this;
}

public SubLogicTwoAble logicTwo (/*Input variables*/){
    // Do logic
    return this;
}
  • Related