Java - how to overwrite getMessage() for custom checked and unchecked exceptions using one implementation?

StackOverflow https://stackoverflow.com/questions/14164901

문제

How to have MyException and MyRuntimeException use the same custom getMessage() implementation?

As Java does not come with multiple inheritance I don't know what to do. At the moment I have duplicate code in both classes...

Important detail: getMessage() does stuff like this.class.getName(). So I do need getMessage() to use reflections cause i need the classname of the object for localization.

So either I need a solution for my first question or a solution on how to use reflections within static methods cause then I could use some utility class which both exceptions could use?

One solution might be a static method in some helper class and then using this:

return new Object() { }.getClass().getEnclosingClass().getEnclosingClass();

Isn't it?

도움이 되었습니까?

해결책

Try making a static shared helper function to implement your custom getMessage:

class MyException extends Exception {
    ....
    public String getMessage() {
        return ExceptionHelper.getMessage(this);
    }
}

class MyRuntimeException extends RuntimeException {
    ....
    public String getMessage() {
        return ExceptionHelper.getMessage(this);
    }
}

class ExceptionHelper {
    public static String getMessage(Exception e) {
        // your shared impl here
    }
}

Edit - if your Exception subclasses have more than just an impl of getMessage copy-pasted between them, you may want to share that as well. A slight tweak of the above to turn the static helper into an encapsulated class will handle this well.

For example: create a class named something like ExceptionDetails, where this shared code and variables (and any other duplication) could live, and each Exception subclass would have their own instance of ExceptionDetails.

다른 팁

You have to put the real implementation of getMessage() into a new concrete class, and delegate to an instance of that class in MyException and MyRuntimeException.

class MyExceptionMessage {
  public String getMessage() { ... }
}

class MyException extends Exception {
  private MyExceptionMessage messager;

  public String getMessage() { return messager.getMessage; }
}

class MyRuntimeException extends RuntimeException {
  private MyExceptionMessage messager;

  public String getMessage() { return messager.getMessage; }
}

You can create an instance of MyExceptionMessage in the constructor of each exception class, or some other way. As you've noted, you're stuck with single inheritance, so there's no way to avoid delegation if you want to reuse the implementation between the two classes.

As Chris has noted, in his answer, a static helper method makes sense, too. At least until your message strategy is complex enough to warrant some instances that you can compose with.

EDIT:

To access the name of the exception class, pass something into to the MyExceptionMessage constructor - you could pass in the exception object, or its class, or the name of the class. You could also define an interface that your exceptions implement, containing a method that tells the messager whatever it needs to know:

interface Messagable {
  public String getMessageFragment();
}

class MyExceptionMessage {
  public String getMessage(Messageable) { 
    return "something" + messagable.getMessageFragment() + "something else";
  }
}

class MyException extends Exception implements Messagable {
  private MyExceptionMessage messager;
  public String getMessage() { 
    return messager.getMessage(this);
  }
}

// class MyRuntimeException would have a similar getMessage() implementation
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top