Kotlin to support package protected visibility

Another point which I don’t think has been made:

In a multiplatform library application, if you have a class in a common source set which is extended by classes in specific platforms, there would seem to be no way of keeping that class private from library users without package private.

Neither internal nor private are of any use here.

Please can we have this feature: it is essential for clean multiplatform development.

Dear Kotlin team and other readers

Since we don’t have package potected visibility, could you plz give me piece of advice how to divide my android project by modules.
I want to split them in both, verticaly (domain, data, presenation) and horizontaly (each feature per module).

So, I have 3 android modules now:
MainPage
Details
Editor

after the dividing they will be like this:
MainPage-domain
MainPage-presentaion
MainPage-data
Details-domain
Details-presentaion
Details-data
Editor-domain
Editor-presentaion
Editor-data

Now we have 9 modules. how do you think this is correct solution in general? I don’t like it because gross amount of my modules will increase very fast if i will be adding more modules in the future. Can you sugget me anthing else?

Thank you

1 Like

How this is related to the lack of package private visibility? I think this is a general question on designing the software.

it is the original reason i asked this question, lack of package private means you have to create bunch of modules if you care slightest about right visibility for your classes, or you put everything that belongs together in one file and make public only what absolutely needs to be public

its still the only downside of kotlin to this day for me, in all other ways this language is superior to anything out there, especially if we assume their native platform support will get as good as jvm support.

Whenever I have to switch from private to package private visibility this feels like a “code smell”. I do use it sometime, but personally for me this feels like one of the worse language features.

Sorry if it’s already been said (long thread)… but what we really want is a internal package access modifier which limits the access to sibling files.

It’s true that package private in java leaks access and the side-effect for testing that granted us is solved with internal.

However, the benefit that package private gave us in java that we were able to break our classes down into smaller parts for cleaner and better cohesive code, rather than shoving everything into one class because it’s hard to communicate.

The alternative is to interface everything, which can sometimes be valuable but often is overkill and becomes a maintenance pain.

I am in favor of package protected access.

Package protected access is a documentation, just like private is. At any point I can go and remove private modifier. At any point I can go and define new classes in the same package.

But it tells me as a developer, in a source repo of 10k-100k files which interface I am meant to use. Often, out of many classes in the same package, only one has “public” API for the rest of the packages. Going into modules does not scale well, because for 100k files you’d have 10k modules, which is absolutely not maintainable, and you also run into limitations of Kotlin compiler regarding smart casting.

internal is too coarse, and private is too restrictive — we need something inbetween.

Just to put in my few cents:

Programming languages are made for Humans.
Package private/protected visibility is convenience for a Developer to impl encapsulation inside module.
It even helps for non-human - IDEs to not s**k during intellisense in a huge codebase.

I argue that this question is more about Jetbrains effort, than about language design

1 Like

I’m sorry then you don’t know how to use it
Unfortunately you used it to hack your way into doing something, not structuring your code for right visibility… There’s a reason Java had it as default not public not private but package visibility.

1 Like

I’d say that both arguments are nonsense…
Security argument is foolish, this has nothing to do with security.
Modules are also no solution, not only no one will create a module for 10 classes, but after 30 or so modules most will say f this and create a monorepo, i have seen this happen way to often… That’s how much people like your modules…

My kt projects these days have massive files where i try to keep things organized.

Until they realize this is necessary i don’t have an alternative.

So in a nutshell there are 0 real arguments, prove me wrong! There are only people who didn’t use this great feature.

1 Like

Having 420 modules speaks nothing about maintainable code…

Most people are going to ignore internal and either create huge files or make everything public but have many files… Look at any kt project it’s very obvious.

No one is going to create a module for 10 classes let’s just agree with that, and if you don’t go search how many open source projects have a single usage of internal.

This is just wrong private method of A is not visible from B even though both are in the same file…

Private has the finest granularity, to the method or field level.

1 Like

No we argue that your love for modules should not be enforced on us.

If i want to keep my code in a monorepo until i see a big enough reason to create a module then i should be able to do it at least as good as i was able to do in Java if not better…

No one tries to replace internal.

I have no idea how people write Java code and don’t use package protected…

2 Likes

It’s a good idea imo especially cos we don’t have to wait for JB to do or not do this …

Biggest issue i see is that idea will probably be very confused about actual visibility.

I think this topic is pretty reasonably a “mega-topic” in that it’s so long it isn’t something anyone can reasonably follow and no one is actively discussing new information.

I’d request this topic be closed to preserve what is already here

If you agree, please avoid posting a reply on this topic (feel free to like). If needed, please discuss on the mega-topic thread–anything to avoid keeping this topic from bumping again.

PS. Maybe when namespaces are new discussion can happen with fresh ideas and perspectives.

5 Likes

It’s 2023, and we still don’t have this feature? What are you guys thinking? Can’t we make it just more simple and functional? I just can’t believe it!

3 Likes

The developers deliberately chose non to have this, I don’t think the passage of time will change that.

1 Like

@vach
I just found that this can be done by creating a private companion object and let it implement some sealed interface.

// kotlin/student/IFirstName.kt
package student
sealed interface IFirstName {
    fun getFirstName(): String {
        return "foo"
    }
}

// kotlin/student/ILastName.kt
package student
sealed interface ILastName {
    fun getLastName(): String {
        return "bar"
    }
}

// kotlin/student/Student.kt
package student
class Student {
    private companion object : IFirstName, ILastName
    fun getFullName(){
        println(getFirstName()+" "+getLastName())
    }
}

// kotlin/Main.kt
import student.Student
fun main(args: Array<String>) {
    Student().getFullName()  //ok
    Student().getFirstName() //not allowed
    Student().getLastName()  //not allowed
}

These codes divide the Student class into three files.
Outside the student package:
1.No class can implement IFirstName or ILastName.
2.No accessibility to get a first name or last name separately.

Maybe not a perfect solution, but makes sense to me.
(Sorry for bad English.)

1 Like

You can also create companion objects in those sealed classes if you want them to call each other.
And if you want to get some properties from Student, just make that function be an extension function.

// kotlin/student/ICheckValid.kt
package student
sealed interface ICheckValid {
    private companion object : IFirstName, ILastName
    fun validName(): Boolean {
        val firstNameLen = getFirstName().length
        val lastNameLen = getLastName().length
        return firstNameLen < 20 && lastNameLen < 20
    }
    fun Student.validAge(): Boolean {
        return age in 1..200
    }
}
// kotlin/student/Student.kt
package student
open class Student(
    var age:Int
) {
    private companion object : IFirstName, ILastName,ICheckValid
    fun getFullName(): String {
        return getFirstName()+" "+getLastName()
    }
}

Having followed this thread for years, I’m also seconding support for package protected visibility. Coming in from Java this is practically the only feature I miss. I’m not really interested in making a complete module when all I want to do is to keep a small piece of code internal and subject to change while only exposing a minimal set for the rest of the codebase.

The fact that you can “beat” this visibility by creating a mimicking package structure is a strength, because you would probably organize your unit tests that way anyway and so they unlock access to what you want. This even lets you use package-local as a built-in test-only accessor, if you so wish.

Finally adding this to kotlin would be very appreciated.

5 Likes