Kotlin의 접근 제한자(Visibility Modifiers)에 대해서 알아보기

접근(가시성)제한자는 객체가 공개되어야 하는 범위를 정해주는 역할을 합니다. 코틀린은 자바와 유사하게 private, protected, internal, public의 접근(가시성, Visibility)제한자를 제공합니다. (참고로, 자바에는 package, public, private, protected의 접근제한자가 있습니다)

패키지 레벨의 접근제한자

코틀린은 Top-level에 클래스와 함수를 정의할 수 있고(파일에서 가장 최상위에 정의된 클래스, 함수, 변수를 의미), 동시에 여러개의 클래스, 함수 등을 정의할 수 있습니다. 또한, 이 객체들에 접근제한자를 붙일 수 있습니다.

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

  • 접근 제한자를 표기하지 않으면 public이 기본으로 설정되며, 누구나 접근이 가능합니다.
  • private으로 표기하면 파일 안에서만 접근이 가능합니다.
  • internal로 표기하면 프로젝트의 모듈 안에서 누구나 접근이 가능합니다.
  • protected는 최상위에(top-level)에 정의되는 클래스, 인터페이스 등에서는 사용할 수 없습니다.

코틀린에서 다음과 같이 Top-level에 함수 또는 프로퍼티에 접근제한자를 붙일 수 있습니다.

package foo

private fun foo() {  }  // 이 파일 안에서만 접근 가능

public var bar: Int = 5 // 어디에서나 접근 가능
    private set         // 이 파일 안에서만 set 접근 가능합니다.

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

패키지 foo 아래에(Top-level) 클래스가 아닌, 함수 또는 프로퍼티를 선언하면 FooKt 클래스를 임의로 만들어 이 안에 멤버 변수와 메소드를 정의합니다. 생성되는 클래스의 이름은 대문자로 시작하는 패키지 이름에 Kt가 붙여 지어집니다.

위의 코틀린 코드를 자바 코드로 변환해서 보면 아래와 같습니다. 접근제한자가 자바에서 어떻게 표현되는지 알 수 있습니다.

public final class FooKt {
    private static int bar = 5;
    private static final int baz = baz;

    private static final void foo() {
    }

    public static final int getBar() {
        return bar;
    }

    public static final int getBaz() {
        return baz;
    }

    public static final void main(@NotNull String[] args) {
        Intrinsics.checkParameterIsNotNull(args, "args");
    }
}

클래스와 인터페이스의 접근제한자

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

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

코틀린에서 다음과 같이 사용할 수 있습니다.

open class Outer {
    private val a = 1
    protected open val b = 2
    internal val c = 3
    val d = 4  // 기본으로 public이 설정됩니다

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

class Subclass : Outer() {
    // a 는 접근할 수 없습니다.
    // b, c, d 는 접근할 수 있습니다.
    // Nested, e 는 접근할 수 있습니다.

    override val b = 5   // 'b' 는 protected
}

class Unrelated(o: Outer) {
    // o.a, o.b 는 접근할 수 없습니다.
    // o.c, o.d 는 접근할 수 있습니다.
    // Outer.Nested와 Nested::e 는 접근할 수 없습니다.
}

위의 코드를 자바로 변환하면 다음과 같습니다.

public class Outer {
    private final int a = 1;
    private final int b = 2;
    private final int c = 3;
    private final int d = 4;

    protected int getB() {
        return this.b;
    }

    public final int getC$kotlin() {
        return this.c;
    }

    public final int getD() {
        return this.d;
    }

    protected final class Nested {
        private final int e = 5;

        public final int getE() {
            return this.e;
        }
    }
}


public final class Subclass extends Outer {
    private final int b = 5;

    protected int getB() {
        return this.b;
    }
}

public final class Unrelated {
    public Unrelated(@NotNull Outer o) {
    }
}

생성자의 접근제한자

생성자에도 접근제한자를 붙일 수 있습니다. 아무것도 붙이지 않은 것은 public 생성자입니다. 누구나 접근이 가능합니다. internal을 붙이면 모듈 내에서만 접근 가능합니다. 반면에, private을 붙이면 클래스 내에서만 접근이 가능하여 외부에서 생성할 수 없습니다.

코틀린에서 private 생성자는 이렇게 만들 수 있습니다.

class Code private constructor(a: Int) {
}

위의 코드를 자바로 변환하면 다음과 같습니다.

public final class Code {
    private Code(int a) {
    }
}

내부에서만 접근이 가능하기 때문에, 클래스의 Companion에 객체를 생성하는 함수를 만들어 사용할 수 있습니다.

정리

접근(가시성)제한자는 객체의 접근이 허용되는 범위를 설정합니다. 접근제한자는 패키지, 클래스, 인터페이스, 생성자 등에 사용될 수 있습니다. 각각의 경우, 접근제한자는 비슷한 의미로 사용되지만 약간 차이가 있는 것들도 있습니다.

참고

Loading script...
codechachaCopyright ©2019 codechacha