Interesting use of Java 8 interface default method

Intro

I was in the middle of trying to implement a type of validation on my current project at work. Said project uses Java 7, and the problem had to do with an interface extending another interface. I was literally in the middle of implementing it, and I said to myself, “I wonder how I could handle this same problem using Java 8!”. So I hopped over to my personal development machine, and gave it a try. First, let me see if I can set forth the problem.

The Problem

Here is the problem we are trying to solve:*
We need the program to behave such that, when we invoke a specific type of validator, we invoke it with the signature specific to that validator. Let me elaborate.

We had an interface like such:

public interface Validator {
  public boolean validate(Thing thingToValidate);
}

We then had 2 other interfaces that extend the Validator interface. (these may look like they have no purpose since they don’t contain any method signatures, but they are marker interfaces used specifically in other parts of the code):

public interface PreProcessingValidator extends Validator {
}
public interface PostProcessingValidator extends Validator {
}

Obviously, we also had the code where the validators get invoked.

/// code removed for brevity...
for(Validator v : validators) {
  v.validate(aThing);
}

This is all great, except we find out that we need the PostProcessingValiator objects to be able to validate also against the ProcessingResult. What can we do? I know one thing! We can just add a method to do that in the PostProcessingValidator:

public interface PostProcessingValidator extends Validator {
  public boolean validatePostProcessing(Thing thing, ProcessingResult result);
}

The problem is now any class that implements the PostProcessingValidator interface needs to implement both the validate(Thing) method and the validatePostProcessing(Thing, ProcessingResult) methods. There are some tricky ways to get around this in Java 7 and below, but I wanted to see what I could do with Java 8. And that’s when interface default methods came to mind. I have no idea if it will actually work or not, but I give it a shot.

The Solution

Java 8 provides for adding default methods to interfaces. This allows you to have interfaces that contain functionality as well as method headers.Let’s take a look at how we can use them to do what we want.

The Validator interface is alright as-is; nothing really needs to change. But we need to allow for classes that implement the PostProcessingValidator interface to not need to implement both methods. here is how I was able to do it:

public interface PostProcessingValidator extends Validator {
  @Override
  public default boolean validate(Thing thing) {
      throw new UnsupportedOperationException("validate(Thing) not supported; call validatePostProcessing(Thing, ProcessingResult");
  }

  public boolean validatePostProcessing(Thing thing, ProcessingResult result);
}

Say what?! I had no idea that this was possible until I tried.

A default method in a sub-interface can ‘override’ that method from a super-interface.

I don’t know all the implications of this behaviors, but I’m not even sure why the designers of Java allowed this sort of override to happen, as it seems like it could be pretty hazardous if not used correctly. I can also think of one gotcha with this approach. A caller can still attempt to invoke validate(Thing), so you need to return to the caller what they need to know what was gone wrong.

The only other code we need to change is the code where we invoke the validators:

/// code removed for brevity...
for(Validator v : validators) {
  if(v instanceof PostProcessingValidator) {  
    v.validatePostProcessing(aThing, aResult);
  } else {
    v.valdiate(aThing);
  }
}

So my conclusion is, you can feel free to use this pattern in your code if you want, although I’m not sure it provides for the best code clarity, or even a good approach to solving the problem. But it does solve this particular problem.

* – all identities in this article have been altered to protect the innocent :-)

Advertisements
This entry was posted in Java, Java 8, Uncategorized and tagged , , , , . Bookmark the permalink.

One Response to Interesting use of Java 8 interface default method

  1. acveer says:

    Sounds interesting. but this feature may create confusion, if the inheritance hierarchy depth increases. I wonder what will happen, if all the sub-interfaces have defined default() implementation.for the same method definition.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s