Kotlin Visibility Modifiers
Overview
A visibility modifier defines the scope in which an object can be accessed.
Types of visibility modifiers
Kotlin provides the visibility modifiers private, protected, internal, and public. They specify the reference scope of variables, functions, class members, and other declarations.
| Type | Description |
|---|---|
public |
Kotlin’s default visibility modifier. It can be accessed from anywhere. |
private |
Accessible only within the corresponding file (.kt) or class. |
protected |
Accessible within the class and from subclasses. It cannot be declared at the top-level. |
internal |
Accessible from anywhere in the same module. |
If no visibility modifier is specified, the declaration is public.
Elements that can have visibility modifiers include class, object, interface, constructor, function, and property. Local variables, local functions, and local classes cannot declare visibility modifiers.
Packages
Functions, properties, classes, objects, and interfaces can be declared directly at the top level inside a package.
// file name: example.kt
package foo
fun baz() { ... } // Accessible only inside example.kt.
class Bar { ... } //
Objects defined at the package level have the following visibility meanings.
- If no visibility modifier is declared,
publicis used by default and the declaration can be accessed from anywhere. - If declared as
private, it can be accessed only within the file (.kt). - If declared as
internal, it can be accessed by anyone inside the project’s module. protectedcannot be declared at the top level.
In Kotlin, you can declare visibility modifiers on top-level functions or properties as follows.
// file name: example.kt
package foo
private fun foo() { ... } // Accessible only inside example.kt.
public var bar: Int = 5 // This property can be accessed from anywhere.
private set // The setter can be accessed inside example.kt.
internal val baz = 6 // Accessible within the same module.
Class and interface members
Visibility modifiers used for members declared inside classes and interfaces have the following meanings.
public: Accessible from anywhere.private: Accessible only inside the class.protected: Accessible inside the class and from inherited objects.internal: Accessible by anyone inside the project’s module.
They can be used as in the following example.
open class Outer {
private val a = 1
protected open val b = 2
internal open val c = 3
val d = 4 // Declared as `public` by default.
protected class Nested {
public val e: Int = 5
}
}
class Subclass : Outer() { // Object that inherits Outer
// Cannot access variable 'a'.
// Can access 'b', 'c', and 'd'.
// Can access `Nested` and 'e'.
override val b = 5 // 'b' is declared as 'protected'.
override val c = 7 // 'c' is declared as 'internal'.
}
class Unrelated(o: Outer) {
// 'o.a' and 'o.b' cannot be accessed.
// 'o.c' and 'o.d' can be accessed. (same module)
// 'Outer.Nested' cannot be accessed, and neither can 'Nested::e'.
}
Constructor visibility modifiers
If no visibility modifier is added to a constructor, every constructor is declared as public (public), so the class can be accessed from anywhere. If private is added, it can be accessed only inside the class and cannot be created from outside. If internal is added, it can be accessed only within the module.
Note: To declare a visibility modifier on a constructor, the constructor keyword must be written explicitly.
class C private constructor(a: Int) { ... }
Here, the constructor is declared as private (private) and can be accessed inside the class.
Modules
According to the official documentation, the same module for internal means the following.
- An IntelliJ IDEA module.
- A Maven project.
- A Gradle source set (with the exception that the
testsource set can access the internal declarations ofmain).- A set of files compiled with one invocation of the
<kotlinc>Ant task.
In short, you can think of the internal modifier as accessible within the same project.