1. Overview
In this article, we’ll describe default access modifiers in Java and Kotlin. After that, we’ll have a look at the definition of a module. Finally, we’ll show how to encapsulate internal logic in Kotlin.
2. Package-Private in Java
Let’s first look at how the default modifier works in Java. It allows us to access the element only from a class in the same package. Additionally, no keyword is required, as it is a default modifier. The Java language allows using the package-private modifier at the top and member levels.
Above all, the package-private modifier doesn’t provide a real encapsulation. For instance, we can put a class in the same package as our package-private class. Then, from the new class, we can access the content of the package-private class. It might be one of the reasons why an identical modifier is not available in Kotlin.
Moreover, if we want to expose a class outside of the package, it must be public. But then, it’s available for everyone.
3. Default Modifier in Kotlin
Now, let’s have a look at the default modifier in Kotlin. *We can use public, private, or internal restriction keywords*. The public modifier is the default one. Additionally, it works the same as in Java. It exposes the class, field, or method to any other code outside of the class.
In Kotlin, there’s no exact substitute for the package-private modifier from Java.
4. Module Definition in Kotlin
Now, let’s consider what a module in Kotlin is. Most importantly, it defines a set of files compiled together in a single jar.
It’s a general definition. Examples include:
- an IntelliJ module
- a Maven project
- a Gradle source set
- a set of files compiled with an Ant task
Modules are important from the internal access modifier’s perspective. Let’s take a closer look at the internal modifier.
5. Use internal to Encapsulate Inner Logic
Now, let’s have a look at how to hide internal logic in Kotlin. The solution in Java, the package-private modifier, is not perfect. Moreover, Kotlin really allows hiding internal logic.
The internal visibility modifier shares similarities with the package–private access modifier from Java, with some benefits. Firstly, it doesn’t expose a member outside of the module. This means we do not expose internal logic outside of the library. On the other hand, we can use an internal class throughout the whole module. This means that it’s encapsulated in our library.
Let’s create a simple example:
internal class InternalClass {
internal fun helloFromInternalFunction(): String {
return "Hello"
}
}
We created InternalClass, which is located inside the com.baeldung.protectedmodifier package. After that, let’s call the internal method from outside of the package:
fun whenCallInternalClass_thenItWorks(){
val internalClass = InternalClass()
assertThat(internalClass.helloFromInternalFunction()).isEqualTo("Hello")
}
The test package is located in the same module. Additionally, we created the test in the com.baeldung.outside.protectedmodifier package*.* Although the test class is located in a different package, it has access to the internal method.
6. Conclusion
In this short article, we described the default modifiers in Java and Kotlin. Then, we briefly discussed the definition of a module in Kotlin. Additionally, we showed how to hide internal logic in the Kotlin language.
As always, the source code of the examples is available over on GitHub.