Kotlin Tutoial
Basics
Control Flow
Array & String
Functions
Collections
OOPs Concept
Exception Handling
Null Safety
Regex & Ranges
Java Interoperability
Miscellaneous
Android
In Kotlin, visibility modifiers determine what other classes have access to a class, method, property, or other member. They are essential for encapsulation in object-oriented programming, allowing for the control of how internal details of a class are exposed (or hidden) from other classes.
Kotlin offers several visibility modifiers:
private
protected
internal
public
Let's delve into each of these:
private
When used in a top-level declaration, such as a function, property, or class outside of another class, it means that the member is only visible within that specific file.
When used inside a class, it means that the member is only visible within that class.
private val privateValue = "I'm private" private class PrivateClass { private val secret = "No one else can see me!" }
protected
This modifier can't be used for top-level declarations.
Inside a class, a protected
member is visible in its class and its subclasses.
open class Parent { protected val protectedValue = "I'm protected" } class Child : Parent() { fun showValue() { println(protectedValue) // Accessible because it's a subclass of Parent } }
internal
An internal
member is visible to all parts of the same module. A module can be a Gradle module, an IntelliJ IDEA module, etc.
This is especially useful in multi-module projects when you want to expose members within the same module but hide them from others.
internal val internalValue = "I'm visible within the same module"
public
This is the default visibility if you don't specify any modifier.
A public
member is visible everywhere its containing class or file is visible.
public val publicValue = "I'm visible everywhere" // 'public' keyword is optional here
In Kotlin, you don't have the package-private level of visibility like in Java (where omitting a visibility modifier allows visibility within the same package). Instead, the closest is internal
, but it's broader since it includes the entire module.
Kotlin visibility modifiers, especially internal
, are designed to provide better encapsulation capabilities, especially in large projects.
Kotlin's visibility modifiers allow developers to control the exposure of classes, objects, and members. By understanding and effectively using these modifiers, developers can write safer, more encapsulated, and maintainable code. Always choose the most restrictive visibility that suits your needs, ensuring that the implementation details are well-encapsulated and that you're only exposing what's necessary.
In Kotlin, visibility modifiers control the accessibility of classes, interfaces, properties, and methods.
package com.example class MyClass { publicVar // Accessible everywhere privateVar // Accessible only within this class protectedVar // Accessible within this class and its subclasses }
If no visibility modifier is specified, the default visibility is public
for classes, interfaces, properties, and methods.
package com.example class MyClass { // This is public by default }
Classes and interfaces can have public
, private
, protected
, or internal
visibility.
// Default is public class PublicClass private class PrivateClass protected class ProtectedClass internal class InternalClass
Properties and methods can also have different visibility modifiers.
class MyClass { publicFun() // Accessible everywhere privateFun() // Accessible only within this class protectedFun() // Accessible within this class and its subclasses }
The internal
modifier makes a declaration visible within the same module.
// Module 1 internal class InternalClass // Module 2 fun main() { val obj = InternalClass() // Accessible within the same module }
internal
visibility ensures that a declaration is visible within the same module but not outside.
// Module 1 internal class InternalClass // Module 2 (Compile-time error) fun main() { val obj = InternalClass() // Not accessible outside the module }
Companion objects share the visibility of their containing class.
class MyClass { companion object { private fun privateFun() {} internal fun internalFun() {} } }
Nested classes have access to their outer class, and inner classes can access private members of the outer class.
class Outer { private val outerVar = 42 class Nested { // Cannot access outerVar } inner class Inner { fun accessOuterVar() = outerVar } }
Extension functions have the same visibility as regular functions.
class MyClass { private fun privateFun() {} fun useExtension() { privateFun() // Accessible from extension function } } // Extension function has access to privateFun fun MyClass.extensionFunction() { privateFun() }
Data classes generate component functions with the same visibility as the properties.
data class Person(private val name: String, val age: Int) fun main() { val person = Person("Alice", 25) val (name, age) = person // Accessible within the same module }
Top-level declarations are visible to everything in the same file by default.
// Visible within the same file private val topLevelVar = 42 fun topLevelFunction() {}
Overriding members must have equal or higher visibility than the overridden members.
open class Parent { protected open fun protectedFun() {} } class Child : Parent() { // Visibility must be protected or public override fun protectedFun() {} }