Wild Goat
Wild Goat

Reputation: 3579

Java generic design

I've ErrorFactory class which based on error code creates an instance of different type of Errors. Also I have Output class which might contains one of those error types.

Code below shows how I am trying to use it, but unfortunately getting error. Could you please help me figure out what is wrong there and suggest better design. Thanks for any help!

OutputLike output = new OutputLike();
ErrorFactory errorFactory = new ErrorFactory();
int errorCode = ((Long)error.get("error_code")).intValue();
output.setError(errorFactory.<Error>getError(errorCode, error));


Error:(97, 27) java: method setError in class com.electronsoftware.VKLiker.responseoutput.output.Output<T> cannot be applied to given types;
  required: com.electronsoftware.VKLiker.error.Error
  found: java.lang.Object
  reason: actual argument java.lang.Object cannot be converted to com.electronsoftware.VKLiker.error.Error by method invocation conversion

======

public class ErrorFactory <T extends Error> {
    public <T> T getError(int error_code, JSONObject errorBody){
        Error.ErrorType errorType = Error.ErrorType.values()[error_code];

        switch(errorType){
            case CAPTCHA_NEEDED:{
                return (T) Parser.parseCaptchaRequiredError(errorBody);
            }
            case USER_AUTHORIZATION_FAILED:{
                break;
            }
            case TOO_MANY_REQUESTS:{
                break;
            }
            case NOT_ENOUGH_PERMISSIONS:{
                break;
            }
            case UNKNOWN:{
                break;
            }
        }
        return null;
    }
}

====

public class OutputLike <E extends Error> extends Output <E> {
    ....
}

public abstract class Output <T extends Error> {

    private boolean isError;
    private T error;

    public boolean isError(){
        return this.isError;
    }
    public T getError(){
        return this.error;
    }
    public void setError(T error){
        this.error = error;
    }
}

====

public static ErrorCaptchaRequired parseCaptchaRequiredError(JSONObject error){

    ErrorCaptchaRequired captchaError = null;
    ....
    captchaError = new ErrorCaptchaRequired(msg, captchaId, captchaUrl);
    return captchaError;
}

====

public class ErrorCaptchaRequired extends Error {
........
}

Upvotes: 0

Views: 89

Answers (3)

Bohemian
Bohemian

Reputation: 424953

Two problems:

A) You are using a raw (untyped) ErrorFactory, which strips all generic info from the instance. Change to:

ErrorFactory<Error> errorFactory = new ErrorFactory<Error>();

B) Even if you fix A), you have typed getError() with <T> that is hiding the type T of the class.
Change

public <T> T getError(int error_code, JSONObject errorBody){

To

public T getError(int error_code, JSONObject errorBody){

Unless you really need to type the factory, I would make it untyped and simply return Error.

Also, naming any class the same as a java.lang class is a bad idea. Call it Problem or something.

Upvotes: 3

ekostadinov
ekostadinov

Reputation: 6940

So based on

and suggest

if you want to consider another approach (tested and working), here is abstract solution. We have base

public class ValidationError{    
   public boolean isExpected() {
     return expected;
   }
}

to contain Error representation and attributes. Also

public class ScenarioError{
    public String getMessage() {
        return message;
    }

}

for test scenarios related errors, so we keep tracking them. Next is

public class ValidationErrorBuilder{
    public List<ValidationError> getValidationErrors(...){
    }
}

to construct found errors. And

public class ScenarioErrorsContainer{
   public String getErrorMessage() {
   }
}

to keep and get for processing already found errors.

Of course you'll have to add some required/needed interfaces (based on your case) in order to achieve better OO design.

Upvotes: 2

Wrench
Wrench

Reputation: 4900

ErrorFactory errorFactory = new ErrorFactory(); instantiates ErrorFactory with the default type, Object. You need to tell what type ErrorFactory should hold, when declaring it.

ErrorFactory<CLASSNAME> errorFactory = new ...

Upvotes: 2

Related Questions