There are two disadvantages: no Java compatibility; and the ability to opt in at the use site. If you have some related modules (and thus public annotation) it still has abi consequences on a technical level. But as long as sun.misc.Unsafe exists people that want to use unstable api can anyway.
@pdvrieze - " A common use for package visibility is to provide access for testing. "
Hmm I am not sure
Suppose that I have a module: article
In my module I have a three packages:
In the Java project (Java 9+) I can have a public facade, interfaces, dtos in a application package also i can have a public interfaces and aggregate class in a domain package and finally all classes in infrastructure which implements those interfaces have package scope visibility. (Others classes in infra have package scope visibility)
So any class from application/domain package can’t call infrastructure impl details directly.
My module can expose only a facade class and dtos classes (jigsaw).
Can you give me the example how it could work in Kotlin (with the same package structure)
Beyond the question whether those should be separate modules, you can use two options:
- Take advantage that a private (top-level) class is accessible to code within that file (file private instead of package private).
- Create 3 annotations:
@Infrastructure. Then annotate the implementations with those annotations. Then you can check that these annotations (or eg. “
@OptIn(Application::class)”) are not used where they should not
I can also use Archunit library…
I am still not convinced…
So I am to understand that Kotlin will never support package scope visibility?
“Never” is a strong word. I think it’s safe to say that
package-private scope is not currently planned–That doesn’t mean that it won’t happen sometime in the future.
As @pdvrieze explains, you can get this kind of scoping now in Kotlin using modules. A second option is to restructure your internal pseudo modules into file-private scopes. Or you could try using OptIn annotations and help evaluate if they may be a superior alternative.
It does seem that a more flexible, internal-to-a-module scoping control is what you want. And yes,
package-private does provide a better means for this internal-to-a-module scoping than
protected in a lot of cases.
Since it seems that a lot of the use cases are either A) inject test code into a scope via placing it under the same package, or B) creating a pseudo module based on a package name, I wonder if the correct questions to ask would instead be the following:
- Can we have an additional scope control mechanism to refine our scopes within a single module? Unlike the internal vs external controls, more fine-grained controls will help organize code.
Can this additional scope control allow for composition without class hierarchy or location restrictions? The current options force you to either place your code inside a specific location (
file-private) or subclass (
protected). The additional control could also not force you to place your code into a specific folder/package (
package visibility scope does provide this kind of more flexible scope control --albeit, in an arbitrary way. In an alternative history, Java could have made scoping based on a class or filename name prefix instead of package path–maybe call it
prefix scope… Glad it wasn’t done that way
A lot has changed since Java’s
package-private scope was decided on. A part of me wonders if Java would have ever added
package-private scope had the module system come first.
IMHO Instead of asking for the same old visibility controls, it’s worth pitting the old
package-private against other solutions that also solve these questions and see which one comes out ahead.
EDIT: I’m surprised I haven’t seen any requests for allowing
protected on top-level declarations. This would allow for
package-private scoping in almost the same way
The structure of the packages should represents my architecture.
I dont think that create a separate maven module for instance - a application with only one class is a good idea - for me is over engineering…
“What we usually consider as impossible are simply engineering problems… there’s no law of physics preventing them.”
- Michio Kaku
In Kotlin and the JVM protected has a different meaning than in the Java language. It means onky accessible by children. Even if you consider that the file scope introduces a class (which is a JVM implementation detail) it can not be inherited.