Consider a package of two Java classes.
class Foo {}
public final class Bar extends Foo {}
Bar implicitly exposes its supertype Foo.
Kotlin's compiler errors when trying to do this.
Could Error Prone check for this in Java? Perhaps Error Prone could offer to make the Foo type public and add a package-private Foo constructor in the above case.
Could you clarify what you mean by "implicitly exposes its supertype?" This seems like a common pattern when you have package-private skeleton implementations with full public implementations, which seems like an actively desirable pattern.
I would think anything listed on the class declaration of a public type would be public API.
What do the JavaDocs look like? Do they list the hidden supertypes of the exposed type, or does the JavaDoc report that Object is the only supertype? (I can look it up if nobody knows offhand.)
On an API design note, it seems inverted to have an abstraction as an implementation detail and an implementation as an API. But, that's tangential to my issue.
@NightlyNexus Guava's com.google.common.graph package uses this idiom, and IIRC the package-private types that the applicable public types extend from are _not_ included in the Guava Javadocs.
For example, the public interfaces Graph and ValueGraph extend from package-private interface BaseGraph, and BaseGraph isn't exposed to users of Guava or mentioned in the Guava JavaDocs.
@NightlyNexus At least, I think I'm right on this. If I understand the JavaDocs correctly, specifically these links to the JavaDocs of Graph and ValueGraph, then there is indeed no mention of BaseGraph unless you navigate to the source code of those classes e.g. Graph.java and ValueGraph.java.
Yeah, I think you're right.
And, https://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html#jls-13.4.4 informs me that changing out hidden supertypes wouldn't break binary compatibility because the linkage would still be in tact.
I suppose the Kotlin compiler is strict here to enforce a design pattern or for concerns with references in inlined code.
Going to close. I think it's weird style (but who am I? :P) but perhaps not a correctness problem in Java.
Thanks for the explanations!
I suppose it's neat that Kotlin disallows this sort of type extension. I agree that this style is weird, and I also think it can easily cause confusion from a reader's perspective, but it seems to me that Guava's graphs package makes ingenious use of it to share common methods across different interfaces, so I'm personally half-okay with it. :)
Most helpful comment
Could you clarify what you mean by "implicitly exposes its supertype?" This seems like a common pattern when you have package-private skeleton implementations with full public implementations, which seems like an actively desirable pattern.