Reputation: 1670
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
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
Reputation: 4596
You would need to downcast it to DerivedClass
, or, use a DerivedClass
instance from the beginning.
Upvotes: 1
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