BrownRecluse
BrownRecluse

Reputation: 1670

Java: Method chaining in derived class

I am writing a DerivedClass (extends SuperClass) with method chaining. For example,

public class SuperClass {
    protected int responseCode;
    protected String responseMessage;

    public void setResponseCode(int code) {
            this.responseCode = code;
    }

    public int getResponseCode() {
            return responseCode;
    }

    public SuperClass withResponseCode(int code) {
            setResponseCode(code);
            return this;
    }

    public void setResponseMessage(String message) {
            this.responseMessage = message;
    }

    public String getResponseMessage() {
            return responseMessage;
    }

    public SuperClass withResponseMessage(String message) {
            setResponseMessage(message);
            return this;
    }

}

And

public class DerivedClass extends SuperClass {
    protected String credentialType;
    protected String credentialId;

    public void setCredentialType(String type) {
            this.credentialType = type;
    }

    public String getCredentialType() {
            return credentialType;
    }

    public DerivedClass withCredentialType(String type) {
            setCredentialType(type);
            return this;
    }


    public void setCredentialId(String id) {
            this.credentialId = id;
    }

    public String getCredentialId() {
            return credentialId;
    }

    public DerivedClass withCredentialId(String id) {
            setCredentialId(id);
            return this;
    }

    public static void main(String[] args) {
            DerivedClass dc = new DerivedClass();
            /*dc.setResponseCode(200);
            dc.setResponseMessage("SUCCESS");
            dc.setCredentialType("MobileIdentifier");
            dc.setCredentialId("678882");*/

            dc.withResponseCode(200)
                    .withResponseMessage("SUCCESS")
                    .withCredentialType("MobileIdentifier")
                    .withCredentialId("678882");

            System.out.println("Derived Class: Code - " + dc.getResponseCode() + " - Response Message - " + dc.getResponseMessage() + " - Credential Type - " + dc.getCredentialType());
    }

}

During compilation of the above I am getting:

DerivedClass.java:41: error: cannot find symbol
                    .withCredentialType("MobileIdentifier")
                    ^
symbol:   method withCredentialType(String)
location: class SuperClass
1 error

Why am I getting this when CredentialType is a field in DerivedClass and not in the SuperClass? How can I chain mixed methods from SuperClass & DerivedClass using the DerivedClass object?

Upvotes: 2

Views: 70

Answers (3)

fps
fps

Reputation: 34470

As others have stated, you are getting that compilation error because the methods of your SuperClass return the SuperClass type, which doesn't contain your DerivedClass's methods.

The correct way to solve this is to make SuperClass abstract and use generics on SuperClass with a recursive type (also called an F-bound type):

public abstract class SuperClass<T extends SuperClass<T>> {

    // TODO attributes, getters and setters

    public T withResponseCode(int code) {
        setResponseCode(code);
        return (T) this; // this cast is absolutely safe!
    }

    // TODO other SuperClass builder methods
}

Then, you can define your DerivedClass as follows:

public class DerivedClass extends SuperClass<DerivedClass> {

    // TODO attributes, getters and setters

    public DerivedClass withCredentialType(String type) {
        setCredentialType(type);
        return this;
    }

    // TODO other DerivedClass builder methods
}

And there won't be any more compilation errors. The downside of this approach is that it forces you to make the SuperClass class abstract, in order to only use the derived classes.

Upvotes: 2

Grzegorz G&#243;rkiewicz
Grzegorz G&#243;rkiewicz

Reputation: 4596

You would need to downcast it to DerivedClass, or, use a DerivedClass instance from the beginning.

Upvotes: 1

scottb
scottb

Reputation: 10084

The method withReponseMessage() returns an object of type SuperClass.

The class SuperClass has no method called withCredentialType() which is why you get the error message.

One strategy for solving this problem is to make SuperClass abstract, and then to define all API methods there, even if the methods are abstract. Otherwise, you will have to cast the object that is returned from the 1st method call (which might make your program vulnerable to mismatch exceptions in the future.

Upvotes: 1

Related Questions