Kotlin 접근 제한자(Visibility modifiers)


개요

접근 제한자(Visibility Modifier)는 객체가 공개되어야 하는 범위를 정하는 역할을 한다. 여기서 Visibility는 가시성으로 번역이 된다.

접근 제한자의 종류

코틀린에서는 private, protected, internal, public의 접근 제한자를 제공하며, 변수나 함수, 클래스 멤버 등의 참조 범위를 지정한다.

종류 설명
public 코틀린의 기본 접근 제한자로써, 어디에서나 접근할 수 있다.
private 해당 파일(.kt) 또는 클래스 내에서만 접근 가능하다.
protected 해당 파일(.kt) 또는 클래스 내에서와 자식 클래스에서는 접근이 가능하다. top-level에서는 선언할 수 없다.
internal 같은 모듈 내에서 어디서든 접근 가능하다.

접근 제한자를 아무것도 붙이지 않으면 public으로 선언된다.

접근 제한자를 가질 수 있는 요소로는 class, object, interface, constructor, function, property 등이 있고, 로컬 변수, 로컬 함수, 로컬 클래스는 접근 제한자를 선언할 수 없다.

패키지 (Packages)

함수, 속성(properties), 클래스, 객체 및 인터페이스는 패키지 내부에서 직접 “최상위(top-level)“에서 선언할 수 있다.

// file name: example.kt
package foo

fun baz() { ... } // example.kt 파일 안에서만 접근이 가능하다.
class Bar { ... } //

패키지 레벨에서 정의되는 객체의 접근제한자는 다음과 같은 의미를 갖는다.

  • 접근 제한자를 선언하지 않으면, public이 기본으로 설정되며, 어디에서나 접근이 가능하게 된다.
  • private으로 선언하면 파일(.kt)안에서만 접근이 가능하다.
  • internal로 선언하면 프로젝트의 모듈 안에서 누구나 접근이 가능하다.
  • protected는 최상위에(top-level)에 선언할 수 없다.

코틀린에서 다음과 같이 최상위(Top-level)에 함수 또는 프로퍼티에 접근 제한자를 선언할 수 있다.

// file name: example.kt
package foo

private fun foo() { ... } // example.kt 파일 안에서만 접근이 가능하다.

public var bar: Int = 5 // 이 프로퍼티는 어디에서든 접근이 가능하다.
    private set         // example.kt 파일 안에서는 setter에 접근이 가능하다.

internal val baz = 6    // 동일 모듈에서는 접근이 가능하다.

클래스와 인터페이스의 맴버들 (Class members)

클래스와 인터페이스 안에 선언되는 멤버들에 사용되는 접근 제한자는 다음과 같은 의미를 갖는다.

  • public : 어디에서나 접근이 가능하다.
  • private : 클래스 내부에서만 접근이 가능하다.
  • protected : 클래스 내부와 상속받는 객체에서 접근이 가능하다.
  • internal : 프로젝트의 모듈 안의 누구나 접근이 가능하다.

다음 예제와 같이 사용할 수 있다.

open class Outer {
    private val a = 1
    protected open val b = 2
    internal open val c = 3
    val d = 4  // 디폴트로 `public`으로 선언된다.

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

class Subclass : Outer() { // Outer를 상속 받은 객체
    // 'a' 변수에는 접근할 수 없다.
    // 'b', 'c', 'd'에서는 접근 할 수 있다.
    // `Nested`와 'e'에 접근할 수 있다.

    override val b = 5   // 'b'는 'protected'로 선언되어 있다.
    override val c = 7   // 'c'는 'internal'로 선언되어 있다.
}

class Unrelated(o: Outer) {
    // 'o.a'와 'o.b'은 접근이 되지 않는다.
    // 'o.c'와 'o.d'는 접근할 수 있다. (같은 모듈)
    // 'Outer.Nested'는 접근할 수 없으며, 'Nested::e'에도 접근 할 수 없다.
}

생성자의 접근제한자

생성자에서 접근 제한자를 붙이지 않으면 모든 생성자는 공개(public)으로 선언되므로 어디에서는 클래스에 접근를 할 수 있다. private을 붙이면 클래스 내에서만 접근이 가능하여 외부에서 생성할 수 없게 된다. internal이 붙게 되면 모듈 내에서만 접근 가능하다.

주의: 생성자에 접근 제한자를 선언하려면 키워드(constructor)를 명시적으로 붙여야 한다.

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

여기서는 생성자는 비공개(private)로 선언되어 클래스 내부에서는 접근이 가능하다.

모듈

여기서 internal에서의 같은 모듈은 공식 문서에 따르면 아래와 같다.

  • An IntelliJ IDEA module.
  • A Maven project.
  • A Gradle source set (with the exception that the test source set can access the internal declarations of main).
  • A set of files compiled with one invocation of the <kotlinc> Ant task.

즉, 같은 프로젝트 내에서는 internal 제한자에 대한 접근이 가능하다고 보면 된다.

참고