변경자 | 클래스 멤버 | 최상위 선언 |
---|---|---|
public | 모든 곳에서 볼 수 있다 | 모든 곳에서 볼 수 있다 |
internal | 같은 모듈 안에서만 볼 수 있다 | 같은 모듈 안에서만 볼 수 있다 |
protected | 하위 클래스 안에서만 볼 수 있다 | (최상위 선언에 적용할 수 없음) |
private | 같은 클래스 안에서만 볼 수 있다 | 같은 파일 안에서만 볼 수 있다 |
가시성 변경자는 코드 기반에 있는 선언에 대한 클래스 외부 접근을 제어합니다. 어떤 클래스의 구현에 대한 접근을 제한함으로써 그 클래스에 의존하는 외부 코드를 깨지 않고도 클래스 내부 구현을 변경할 수 있습니다.
코틀린의 기본 가시성은 자바와 다른데, 아무 변경자도 없는 경우 선언은 모두 공개(pubilc)됩니다.
자바의 기본 가시성인 패키지 전용(package-private)은 코틀린에 없습니다. 코틀린은 패키지를 네임스페이스를 관리하는 용도로만 사용하기 때문입니다.
패키지 전용 가시성에 대한 대안으로 코틀린에는 internal이라는 새로운 가시성 변경자가 도입되었습니다. internal은 "모듈 내부 에서만 볼 수 있음"이라는 뜻입니다. 여기서 모듈(module)은 한 번에 한꺼번에 컴파일되는 코틀린 파일들을 의미합니다.
코틀린에서는 최상위 선언에 대해 private 가시성(비공개 가시성)을 허용한다는 점입니다. 그런 최상위 선언에는 클래스, 함수, 프로퍼티 등이 포함됩니다. 비공개 가시성인 최상위 선언은 그 선언이 들어있는 파일 내부에서만 사용할 수 있습니다.
자바에서는 같은 패키지 안에서 protected 멤버에 접근할 수 있지만, 코틀린에서는 그렇지 않다는 점에서 자바와 코틀린의 protected가 다르다는 사실에 유의해야 합니다. protected 멤버는 오직 어떤 클래스나 그 클래스를 상속한 클래스 안에서만 보입니다. 이전에 확장 함수에서 보았듯이 클래스의 확장 함수는 그 클래스의 private이나 protected 멤버에 접근할 수 없습니다.
코틀린에서는 외부 클래스가 내부 클래스(inner)나 중첩 클래스의 private 멤버에 접근할 수 없습니다.
open class Parent {
// protected로 선언하였기에 자기 자신 또는 하위 클래스에서 사용 가능
protected open val name = "코틀린"
// class의 private으로 선언해서 클래스 내에서만 접근 가능
private val address = "대한민국"
// 아무런 가시성이 없기에 public에 해당
open val tel = "00000"
}
// Parent 클래스를 상속 받음
class Child: Parent() {
fun call() {
// protected 멤버에 접근
println(name)
// public 멤버에 접근
println(tel)
// private 멤버에 접근 불가능(에러)
println(address)
}
}
fun main() {
val parent: Parent = Parent()
// protected 멤버에 접근 불가능(에러)
println(parent.name)
// private 멤버에 접근 불가능(에러)
println(parent.address)
// public 멤버에 접근 가능
println(parent.tel)
}
위 예시는 Parent라는 기반 클래스, Child라는 하위 클래스를 선언하고 기반 클래스에 선언된 가시성에 따라서 접근할 수 있는 멤버를 확인하기 위해 작성한 코드입니다. 아무것도 선언하지 않은 tel은 public이기에 모두 접근이 가능하고, 클래스 안의 private 멤버인 address는 클래스 안에서만 접근이 가능하기에 그 밖에서 접근하려면 오류가 발생합니다. 그리고 protected 가시성을 가진 name은 자기 자신과 하위 클래스에서는 접근 가능하지만 그 밖에서는 접근이 불가능하기에 main()에서 접근하면 오류가 발생합니다.