Using default keyword in interface correctly

Viewed 537

I have a co worker who need a method to be available to two classes.

He decided to create a new interface to be implemented by those classes.

The interface has one method default doThis(String parameter)

It does not have any other interface methods, there is no indication that other methods would be added to this interface.

I feel this is an incorrect usage of the interface and it should be done in a different way. I.e perhaps a class which has the method allowing other classes to consume this by using the object.

Does anyone with experience on this have any opinions to share?

I can update with more clarification based on your comments.

Update:

Here is the code and the question remains: is this a valid use of the default method or should this common logic have been done in another way like a Utilities class which does the saving to preferences ?

Interface:

public interface LogInCookie {

    default void mapCookiesToPreferences(String cookie) {
        if (cookie.contains(MiscConstants.HEADER_KEY_REFRESH)) {
            String refreshToken = cookie.replace(MiscConstants.HEADER_KEY_REFRESH, StringUtils.EMPTY);
            SharedPrefUtils.addPreference(SharedPrefConstants.REFRESH_TOKEN, refreshToken);
        } 
    }
}
public class HDAccountActivity extends AbstractActivity implements LogInCookie {

    private void mapCookies(List<String> mValue) {
       LogInCookie.super.mapCookiesToPreferences(mValue); //ekh!
    }

}
public class BaseSplashPage extends AppCompatActivity implements DialogClickedCallBack, LogInCookie {

//method which uses this
private void mapCookiesToPreferences(List<String> headers) {
        int firstItemInHeader = 0;
        for (String header : headers) {
            String  mValue =  header.substring(firstItemInHeader,header.indexOf(MiscConstants.SEMICOLON));
            LogInCookie.super.mapCookiesToPreferences(mValue);  //ekh!
        }
    }

}
4 Answers

A default method in an interface, which doesn’t define other methods, can’t do much useful things with the instance of the implementing class. It can only use methods inherited from java.lang.Object, which are unlikely to carry semantics associated with the interface.

If the code doesn’t use instance methods on this at all, in other words, is entirely independent from the this instance, you should make it static, change the containing class to a non-instantiable class type, i.e.

final class SomeUtilClass {
    static void doThis(String parameter) {
    // ...
    }

    private SomeUtilClass() {} //no instances
}

and use import static packageof.SomeUtilClass.doThis; in the classes using this method.

That way, all these classes can invoke the method like doThis(…) without a qualifying type name, without needing a misleading type hierarchy.

When the method actually uses the this instance, which, as said, can only be in terms of methods inherited from java.lang.Object, the type inheritance might be justified. Since this is rather unlikely, you might still consider the type hierarchy to be misleading and rewrite the code to

final class SomeUtilClass {
    static void doThis(Object firstParameter, String parameter) {
    // ...
    }

    private SomeUtilClass() {} //no instances
}

using firstParameter instead of this, which can be invoke like doThis(this, …).

Ideally you would put that method doThis() in an abstract class that both classes extend. However if you need to achieve multiple inheritance then using an interface here is fine.

A class with a static method doThis() that you can call staticly would also work.

It all depends on how you have your project organized imo.

In java 8 , default keyword in interface was introduced for those cases where if any set of apis had long inheritance hierarchy and we wanted to introduce a method that should be available in all of the lower lying classes.

So for ex. in Java 8 stream() method was introduced in the Collection interface as a default method and it ended up being available in all of the underlying classes.

As far as your case in considered , if I go by your words then if yours is a new development then you should be using interface -> abstract class -> actual implementing class.

Only if yours was an older development setup and you already had classes implementing from an interface , that could have been an ideal scenario for using default method in your interface.

A default method in an interface
*)can have a default implementation
*)which can overridden by the implementing class

yes its a correct usage since JAVA8.
we can have default method in an interface as well as a abstract method

Related