Exploring Kotlin's Visibility Modifiers: Scope Rules for Top-Level, Class, and Module Declarations

Kotlin provides four visibility modifiers: private, protected, internal, and public. The default visibility, when no modifier is explicitly applied, is public.

Top-level declarations—such as functions, properties, classes, objects, and interfaces—live direct within a package:

// File name: utils.kt
package com.sample.utils

// Visibility rules apply here:
// - public: accessible everywhere (after proper import)
// - private: only visible within utils.kt
// - internal: visible across all files in the same module
// - protected: NOT allowed for top-level declarations

private fun formatTimestamp(): String { /* ... */ }

public var userCount: Int = 0
    private set // Only the setter is restricted to utils.kt

internal val MAX_RETRY_ATTEMPTS = 7

For members declared inside a class or interface:

open class Container {
    private val secretCode = 9876
    protected open val sharedKey = "alpha123"
    internal val moduleConfig = mapOf("timeout" to 3000)
    val publicLabel = "Sample Container" // Defaults to public

    protected class InnerHelper {
        val helperId: String = "helper_01"
    }
}

class ExtendedContainer : Container() {
    // secretCode is not visible
    // sharedKey, moduleConfig, publicLabel are visible
    // InnerHelper and helperId are visible
    override val sharedKey = "beta456" // Overridden member retains protected visibility
}

class ExternalChecker(container: Container) {
    // container.secretCode, container.sharedKey are not visible
    // container.moduleConfig and container.publicLabel are visible if same module
    // Container.InnerHelper and InnerHelper.helperId are not visible
}

To control the visibility of a class’s primary constructor, add an explicit constructor keyword with the modifier before it:

class SecureVault private constructor(initialPass: String) { /* ... */ }

By default, all constructors are public, which means they are accessible wherever the class itself is visible (e.g., an internal class’s constructor can only be used within the same module).

Local variables, functions, and classes cannot have visibility modifiers.

The internal modifier restricts access to members within the same module, where a module is a set of Kotlin files compiled together. Examples of modules include:

  • A IntelliJ IDEA module
  • A Maven project
  • A Gradle source set (with the test source set having special access to main source set internal declarations)
  • A collection of files compiled via a single <kotlinc> Ant task

Tags: kotlin Visibility Modifiers Kotlin Classes Kotlin Modules Kotlin Syntax

Posted on Thu, 23 Jul 2026 16:52:14 +0000 by elementaluk