使用 public 方法从 Java class 继承,在 Kotlin 中接受受保护的 class

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

我遇到这种情况: 有一个Javaclass

public class A {

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

    protected static class B {

    }
}

和一个 Kotlin class,继承自它并且必须重写方法 "overrideMe"

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

但是 Kotlin 不允许这种行为。

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

有什么办法可以解决这个问题吗?

P.S。这不仅仅是一个综合案例 - 我在尝试实现自定义 Spring AmqpAppender 并覆盖它的 postProcessMessageBeforeSend 方法时遇到了这个问题。

在 Kotlin 中无法解决这个问题,原因如下:

区别在于 protected 在 Kotlin 中的实际含义与在 Java 中的含义略有不同。

protectedKotlin 中表示:

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

protectedJava 中表示:

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.

有了这些知识,问题应该很清楚了,Kotlin 中的 protected static class B 更像是 Java 中的 private static class B。因此警告是正确的。

Kotlin-Java Interop 指南明确指出:

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);

结论:

这意味着 Kotlin 将 Java-protected 解释为好像它是 Kotlin-protected 因此没有办法在 Kotlin 中按原样实现 class K。至少你必须做的是创建 C extends A(在 Java 中)来处理 B 的所有 public 访问,然后在 Kotlin 中扩展这个 class .喜欢本期Calling protected static methods

罪魁祸首:

主要问题是Javastatic nested classes的行为,

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.

这种便利行为首先造成了问题。

旁注:

可能更适合 Java-protected 的是 Kotlins internal,它提供了更好的封装级别。

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

嗯,毕竟结论是:纯Kotlin没有办法解决这种情况。

希望不久的将来AmqpAppender.Event变成public

即使 Java 允许这种行为,在 public 方法中使用 no-public 参数对我来说似乎是一个糟糕的设计(对于 Kotlin 的开发者也是如此)。