Learn Kotlin Visibility Modifiers — private, protected, internal, public

Encapsulation is one of the important features of object-oriented programming.

It is the process of wrapping up of data and information under a single unit.

Consider an example of a school management system. In school, we have various departments like the accounts department, library department, faculty department, student department, etc. All these departments have their information. But a situation may arise when an employee from the accounts department requires the information of the library department(maybe details of fine). In this case, the accounts department should not be allowed to directly access the information of the library department. The employee from the accounts department should first contact some officials from the library department and that officer will provide the required details. The above process is called Encapsulation because all the information related to a particular department is grouped and no one is allowed to access it unless granted the access.

In a programming language, the concept of Encapsulation is implemented with the help of access specifiers or access modifiers. In this blog, we will learn about various Visibility Modifiers or access specifiers like public, protected, internal, and private in Kotlin. So, let’s get started.

What is visibility modifier?

Visibility modifier or access specifier or access modifier is a concept that is used to define the scope of something in a programming language. Let’s take the previous example of a school management system. In that example, the employee from the accounts department is not allowed to directly access the details of library department. So, the scope of visibility is defined with the help of visibility modifiers.

In Kotlin, we have four visibility modifiers:

  • private
  • protected
  • internal
  • public

By default, the visibility modifier in Kotlin is public.

Private Modifier

If you are using the private modifier in the declaration then it will be visible inside that particular class or file containing the declaration.

// Private modifier example

// Visible just inside this file
private const val noOfStudents = 1000

// Visible just inside this file
private class Student() {
    
    // Visible just inside the Student class
    private val newCount = noOfStudents
}

// ERROR: newCount is not accessible outside the Student class
private const val finalCount = newCount

In the above example, we are having three private variables and one private class. The private variable noOfStudents and the private class Student is visible inside the file. While the private variable newCount is only visible inside the Student class and this is the reason why it shows an error when we try to use this newCount variable outside the class i.e. outside its scope.

Protected Modifier

If you are using the protected modifier in the declaration then it will be visible inside that particular file containing the declaration and also in the subclass of that particular class. It is not allowed for top-level declarations.

// Protected modifier example

// Visible just inside this file
private const val noOfStudents = 1000

// Visible just inside this file
open private class Student() {

    // Visible just inside the Student class and its subclass
    protected val newCount = noOfStudents
}

// Visible inside this file
private class StudentManager : Student() {
    // Visible inside the StudentManager class
    // newCount is visible because StudentManager is a subclass of Student
    private val finalCount = newCount
}

// ERROR: protected modifier is not allowed for top level declarations
protected const val noOfStudent = 10000

// ERROR: protected modifier is not allowed for top level declarations
protected class Staff()

In the above example, the newCount variable will be accessed from the subclass also because it is declared protected and it can be accessed from anywhere in the file and from the subclass. Also, you can notice that the top-level declaration is not allowed here.

Protected methods overriding

When we are overriding a protected method then the visibility of the overridden method is also protected and it will be visible inside that particular file.

// override protected method example

open private class Student() {
    protected open fun getCount() = 1000
}

private class StudentManager : Student() {
    // getCount() inherits the protected modifier as default
    override fun getCount() = 2000
}

In the above example, the getCount() method of the StudentManager class is also protected and not public.

Internal Modifier

While developing a project, we make various modules in the project. For example, we can have separate modules for login and registrations. So, you can think of a module as a set of Kotlin files that are compiled together.

If you are using the internal modifier in the declaration then it will be visible everywhere in that particular module. By the term module, we mean to say those files that are compiled together. The internal modifier is beneficial only when we are having more than one modules in a project. Otherwise, we can use a public modifier (don’t worry, it is discussed in the next part of the blog). For example, we are having two modules named Module1 and Module2.

// Internal modifier example
//Module1

// Visible to everyone in the same module i.e. in Module1
internal const val noOfStudents = 1000

// Visible to everyone in the same module i.e. in Module1
internal open class Student() {
    // Visible to everyone in the same module i.e. in Module1 that has visibility on Student
    internal val newCount = noOfStudents
}

In the above code, we have two variables named noOfStudents and newCount that are present in Module1 and are declared as internal.

// Module1 but different file

// noOfStudents is visible because this file is in the same module i.e. in Module1
// newCount is visible because this file is in the same module than Student i.e. in Module1
private const val finalCount = noOfStudents

The above file is in the same module i.e. the Module1. Here, we can access the noOfStudents and newCount because these variables are in the same module and are declared as internal.

// Module2 i.e. different module

// ERROR: noOfStudents is not visible because this file is in a different module i.e. Module1
// ERROR: finalCount is not visible because Student() is in a different module i.e. Module1
private const val finalCount = noOfStudents

Here, in the above code, the noOfStudents and finalCount is not visible because these are present in some other module i.e. Module1 and we are trying to access these from different module i.e. Module2.

Public Modifier

If you are using the public modifier in the declaration then it will be visible to everyone. By default, the visibility modifier in Kotlin is set to public.

// Public modifier example

// Visible everywhere
public const val noOfStudents = 1000

// Visible everywhere
public open class Student() {
    // Visible to everyone with visibility on the Student class
    public val newCount = noOfStudents
}

// Visible everywhere
public class StudentManager() {
    // finalCount is visible to everyone with visibility on the StudentManager class
    // newCount is visible because Student is public and newCount is public
    public val finalCount = noOfStudents
}

In the above code, the variables are declared as public. So, they can be accessed from everywhere i.e. from a different class or different files also.

Constructor

By default, the visibility of a constructor is set to public. But you can change the visibility of the constructor as per your choice.You need to add an explicit constructor keyword.

class C private constructor(a: Int) { ... }

In the above code, the visibility of the constructor is private.

Conclusion

In this blog, we learned about various visibility modifiers in Kotlin i.e. private, protected, internal, and public. By default, the visibility is set to public and by doing so, it can be accessed from anywhere. If you declare something as private then it will be accessed from that class or file(if declared globally) only. While in case of protected, the visibility is only set to that particular file.

Hope you learned something new today.

Do share this blog with your fellow developers to spread the knowledge. You can read more blogs on Android on our blogging website.

Apply Now: MindOrks Android Online Course and Learn Advanced Android

Happy Learning :)

Team MindOrks!