Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inheritance from Java class with a public method accepting a protected class in Kotlin

I have this situation: There are a Java class

public class A {

    public void overrideMe(B param){
        //TODO: override me in Kotlin!
    }

    protected static class B {

    }
}

and a Kotlin class, which inherits from it and has to override method "overrideMe"

class K: A() {
    override fun overrideMe(param: B) {
        println("Wow!")
    }
}

But Kotlin doesn't allow this behaviour.

'public' function exposes its 'protected (in A)' parameter type B

Is there any way how to resolve this one?

P.S. It's not just a synthetic case - I faced this problem when I tried to implement custom Spring AmqpAppender and to override it's postProcessMessageBeforeSend method.

like image 418
Nikolay Romanov Avatar asked Mar 14 '18 17:03

Nikolay Romanov


People also ask

Can protected class be inherited in Java?

The protected access modifier is accessible within the package. However, it can also accessible outside the package but through inheritance only.

How do you allow a class in Kotlin to be inherited from another class?

In Kotlin, all classes are final by default. To permit the derived class to inherit from the base class, we must use the open keyword in front of the base class. Kotlin Inheriting property and methods from base class: When we inherit a class then all the properties and functions are also inherited.

Which inheritance is not supported in Kotlin?

Kotlin does not support multiple inheritance.

Is protected method inherited?

protected means access to the method is restricted to the same package or by inheritance. So the answer is, yes, protected methods can be overridden by a subclass in any package. By contrast, package (default) scoped methods are not visible even to subclasses that are in a different package.


Video Answer


1 Answers

There is no way to resolve this in Kotlin, and here is why:

The difference is that protected actually means something subtly different in Kotlin than in Java.

protected in Kotlin means:

kotlin protected: same as private (visible inside the file containing the declaration) + visible in subclasses too;

protected in Java means:

java protected: the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.

And with this knowledge the issue should be clear, the protected static class B in Kotlin is more like private static class B in Java. Therefore the warning is correct.

The Kotlin-Java Interop guide specifically states:

protected remains protected (note that Java allows accessing protected members from other classes in the same package and Kotlin doesn't, so Java classes will have broader access to the code);

Conclusion:

This means that Kotlin interprets the Java-protected as if it was a Kotlin-protected ergo there is no way to implement the class K in Kotlin as it is. The least you must do to make it work is create C extends A (in Java) that handles all public access of B and then extend this class in Kotlin. Like in this issue Calling protected static methods

The culprit:

The main problem is Javas behaviour of static nested classes, which

interacts with the instance members of its outer class (and other classes) just like any other top-level class. In effect, a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience.

This convenient behaviour creates the problem in the first place.

Side note:

Probably the better match for Java-protected is Kotlins internal which provides a better level of encapsulation.

kotlin internal: any client inside this module who sees the declaring class sees its internal members;

like image 103
leonardkraemer Avatar answered Oct 18 '22 11:10

leonardkraemer