Encapsulation is a huge part of OOP. Hiding method and behavior is an important part in achieving encapsulation so Kotlin provides us with access modifiers to help in this effort.
Kotlin has four kinds of access modifiers
- private—Items marked as private are visible only to the class
- protected-Items marked as protected are visible to the class and it’s child classes
- internal—Items marked as internal are accessible to all members of the Kotlin module but are not available outside of the module
- public—Items marked as public are available to the module and outside of the module using the import statement
-
Let’s walk through some examples.
Public
Public is the default visiblity in Kotlin. If the public keyword is omitted, the member will be marked as public.
fun printBurgerOfTheDay(burgerName : String = "Never been Feta") = println(burgerName)
The printBurgerOfTheDay function is accessible to all code within the module that contains it, plus any module that imports the printBurgerOfTheDay function.
Internal
Members marked as internal are visible to the module but are not accessible outside of the module. In other words, internal members act like public members, but they can’t be imported into other modules.
internal var burgerName = "Mission A-Corn-Plished Burger"
The above variable can be accessed in the module. It may not be imported into another module.
Protected
While public and internal access can be used on both class and non-class members, protected only applies to classes.
open class Cook { protected val position = "Cook" private val name = "No Name" override fun toString(): String { return position + ", " + name } } class Bob : Cook() { fun printPosition() = println(position) }
In the above example, we have a Cook and a Bob class. The Cook class has a protected property called position. The position property is accessible to Cook but it’s also accessible to Bob because Bob is a child class of Cook. In the above example, Bob has a printPosition() function that uses the position property.
Private
Private access is the most restrictive. When a member is marked as private, it is only accessible to the class. In the above code snippet, Cook also has a name property, but the name property is not accessible to Bob because it is private.
Putting it all together
Below is an example program that shows all of the possible access modifiers in question.
package ch1.accessmodifiers /** * When no access modifier is used, public is used by default. * This printBurgerOfTheDay function is visible to the entire program */ fun printBurgerOfTheDay(burgerName : String = "Never been Feta") = println(burgerName) /** * This extension function is marked private. It can't even be used in this module */ private fun String.makeBurgerOfTheDay(burgerName : String) : String = burgerName /** * This variable is marked as internal. It's visible throughout the module, * but it can't be accessed outside of the module */ internal var burgerName = "Mission A-Corn-Plished Burger" /** * The position property on Cook is marked as protected. It is only accessible * to the Cook class an it's child classes. The name property is private and may * only be used by Cook. */ open class Cook { protected val position = "Cook" private val name = "No Name" override fun toString(): String { return position + ", " + name } } class Bob : Cook() { fun printPosition() = println(position) } fun main(args : Array<String>){ //Using the public function printBurgerOfTheDay printBurgerOfTheDay() //Printing the internal burgerName variable printBurgerOfTheDay(burgerName) //Create an instance of Cook val cook = Cook() println(cook) //Create an instance of Bob val bob = Bob() bob.printPosition() //try and use the String extension function //DOESN'T COMPILE because makeBurgerOfTheDay is private //burgerName = String.makeBurgerOfTheDay("Rest in Peas Burger") }
Here is the output when run
Never been Feta Mission A-Corn-Plished Burger Cook, No Name Cook
References
https://kotlinlang.org/docs/reference/visibility-modifiers.html