Skip to content

Kotlin visibility modifiers

1. Overview

In this article, we will go through all the visibility modifiers supported by Kotlin

2. Access modifiers kotlin

As the name suggests, the visibility modifier controls the visibility or accessibility of declarations (classes, objects, interfaces, constructors, functions, properties, and their setters). But local declarations (local variables, functions, and classes) can’t have visibility modifiers.

class A {

  fun print() {
     val text = "This local variable can't have visibility modifier"
     println(text)

  }
}

If you specify any visibility modifier to the local variable text, then the compiler would throw the error “Modifier ‘public’ is not applicable to ‘local variable'”.

We have four visibility modifiers in Kotlin: 

  • private
  • protected
  • internal
  • public (default)

2.1. public – Kotlin default access modifier

If you don’t specify any visibility modifier for your declaration, the public modifier is used by default. This would make your declaration visible everywhere.

The default modifier in Java is package-private, meaning all declarations are visible within the same package. But aren’t accessible from other packages.

We would directly declare the functions, properties, classes, objects, and interfaces at the “top-level” inside a package.

package tedblob

fun print() { ... }
class Bar constructor(val a: Int, val b: Int) { 
   fun calculate() : Int { return a+b }
}

Since we have specified no modifiers, the above top-level print function and Bar class is public and visible everywhere. The calculate() function inside the Bar class is also public. So we can access calculate function from anywhere.

import com.tedblob.Bar
package consumer

fun print() { Bar(5, 10).calculate() }

From another package consumer, we are able to access the calculate function of Bar class.

The constructor of a class is also public by default if no visibility modifier and being visible everywhere the class is visible. As a result, you are able to instantiate your Bar class using its constructor from the consumer package.  

2.2. private modifier

If you mark a declaration as private, it will only be visible inside the same scope that contains the declaration.

If you specify any top-level declarations as private, then it is visible only to the members of the same scope.

Suppose, you declared the top-level print function as private, it is visible only within the tedblob.kt file. Any members of Bar class can access the print function as they all are in the same scope.

This print function will not be accessible outside this tedblob.kt file.

package tedblob

private fun print(str: String) { println(str) }
class Bar constructor(val a: Int, val b: Int) { 
   fun calculate() : Int { 
      print("a : " + a + "\nb :" + b)
      print(isLarger(a, b))
      return a+b 
   }
    
   private fun isLarger(a: Int, b: Int) : Boolean {
      return a > b
   }
}

class Foo private constructor(val c:Int) {
}

Let’s take an example of the private class member. In the above example, isLarger function is private and would be accessible with the class Bar but not outside of it.

The constructor of Foo class is private so we can’t instantiate this class outside of this tedblob.kt file.

2.3. Kotlin protected modifier

The protected modifier in Kotlin means the class members have the same visibility as private but are also visible in subclasses. The protected modifier in Kotlin is not available for top-level declarations.

open class BaseClass {
    protected open val b = 2

    protected class Nested {
        private val e: Int = 5
    }

    fun print() {
       Nested().e 
    }
}

class Subclass : BaseClass() {


    override val b = 5   
}

class Other(o: BaseClass) {

}

In the above example,

  1. If you override a protected member in your subclass and do not specify any visibility explicitly, the overriding member will also have the same visibility. Therefore, the variable b is protected in both BaseClass and SubClass.
  2. We can’t access private members of Nested inner class from the outer class BaseClass.
  3. BaseClass protected members are accessible only from its subclasses.

2.4. Internal kotlin modifier

The internal visibility modifier means that the declaration is visible within the same module. You can add internal to all the top-level declarations, class members, constructors. A module is a set of Kotlin files compiled together and independent of one another. You can reuse the module in multiple projects. It can be a jar file, maven project, so on. If you declare internal modifier to:

  1. Top-level declarations – Accessible anywhere within the same module.
  2. Class members – Accessible anywhere within the same module but limited by the class scope. Wherever the class is visible inside the same module, the internal class members also visible.
open class Base {
    internal val c = 3
}

class Subclass : Base() {


}

class SameModuleClass(o: Base) {

}

class OtherModuleClass(o: Base) {

}

4. Kotlin class modifiers

Kotlin class supports all of the modifiers discussed above. The declaration would be as:

<access_modifier> class <class_name> { ... }

<access_modifier> can be private, protected, internal and public.

4. Conclusion

In this article, you have learned about the Kotlin visibility modifiers along with few examples.

2 thoughts on “Kotlin visibility modifiers”

  1. Pingback: Kotlin jvmfield vs const modifier for constant - TedBlob

  2. Pingback: Kotlin field vs property - Member variables - TedBlob

Leave a Reply

Your email address will not be published. Required fields are marked *