Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Protect "default" methods from overriding

Tags:

java

java-8

I'm looking for a solution, that allows to protect the default methods from inheritance. The easiest solution could be - extend from class and etc... but in my case it's not possible.

Can someone suggest how to solve this problem? Could there be any workarounds?

Atm I have following code, which needs to be reworked (if/any possible):

public interface MyInterface1 {
    default boolean isA(Object obj) {
         return (boolean) obj.equals("A") ? true : false;
    }

    default boolean isB(Object obj) {
         return (boolean) obj.equals("B") ? true : false;
    }
}

public class MyClass extends MyLogic implements MyInterface, MyInterface1 {
// this class allows to inherit methods from both interfaces,
// but from my perspective i'd like to use the methods from MyInterface1 as it is,
// with a 'protection' from inheritance. is that possible?
}
like image 593
Malakai Avatar asked Jan 09 '17 20:01

Malakai


People also ask

How do you protect a method overriding?

The final way of preventing overriding is by using the final keyword in your method. The final keyword puts a stop to being an inheritance. Hence, if a method is made final it will be considered final implementation and no other class can override the behavior.

Can default methods override?

A default method cannot override a method from java. lang. Object . The reasoning is very simple, it's because Object is the base class for all the java classes.

Which two declarations prevent the overriding of a method?

In short, apart from final modifier, you can also use static and private modifier to prevent a method from being overridden.

Can we override a protected method of parent class?

Yes, the protected method of a superclass can be overridden by a subclass.


1 Answers

You seem to want a way to write your interface so that implementing classes cannot provide their own implementations of its default methods. There is no way to do this, and indeed it runs counter to the purpose of interfaces in general and default members in particular.

The point of default methods is to provide a way to add methods to existing interfaces without instantly breaking all their existing implementations. Generally speaking, this is a binary compatibility issue, not a functionality issue. There's no particular reason to suppose in general that default implementations can provide the intended functionality, but without them, even old code that doesn't rely on the new methods at all is incompatible with interface revisions that add methods.


I think you have a factoring issue. Rather than trying to force classes to provide a specific implementation of a specific method -- which cannot even refer to that class's members, except possibly others defined by the same interface -- you should provide the common methods in a class of their own. After all, since you want all classes involved to provide identical implementations, it doesn't matter which class's implementations you actually use. Moreover, there is therefore no particular usefulness in marking any given class as providing implementations of the well-known methods.

Example:

public class MyImplementation1 {
    public static boolean isA(Object obj) {
         return obj.equals("A");
    }

    public static isB(Object obj) {
         return obj.equals("B");
    }
}

// Wherever needed, use as MyImplementation1.isA(o), etc.

You can do this even if you want these pre-baked implementations to operate in terms of the other methods of your interface. In that case, just add an argument to the fixed methods that provides the object to operate on. Perhaps that's what the obj arguments in your example were supposed to be; in that case, this may be closer to what you're after:

public interface MyInterface3 {
    public String someInterfaceMethod();
}

public class MyImplementation2 {

    public static boolean isA(MyInterface3 subject) {
         return subject.someInterfaceMethod().equals("A");
    }

    public static boolean isB(MyInterface3 subject) {
         return subject.someInterfaceMethod().equals("B");
    }
}
like image 119
John Bollinger Avatar answered Sep 29 '22 00:09

John Bollinger