티스토리 뷰

프로그래밍언어/Kotlin

Kotlin 접근 제한자

데니 Denny 2019. 7. 28. 15:27
반응형
SMALL

2019-07-28 Kotlin 상속 (Kotlin Override) - 1

2019-07-28 Kotlin 상속 (Kotlin Override) - 2

이전 글에 이어서 진행합니다. 아직 학습을 못하신 분들은 위 링크를 따라 들어가서 학습을 하신 후 다시 오시기 바랍니다.

 

이번 포스트에서는 Kotlin 언어에서의 접근 제한자에 대해 알아보도록 하겠습니다.

public class User {
    public constructor() {}

    public val name: String = "KIM"
    public fun myFun() {

    }
}

코틀린에서 제공하는 Access Modifier에는 4가지가 있습니다.

public, internal, protected, private

접근 제한자의 접근 제한 범위

최상의 구성요소의 접근 제한자

프로퍼티와 함수를 최상위 레벨에 작성한다는 것은 클래스에 멤버로 포함하지 않고 코틀린 파일에 정의하는 것을 의미합니다.

package kotlin_study

public val myData: Int = 10
public fun myFun() {}
public class myClass() {}

이렇게 최상위 레벨에서 접근 제한자를 사용하여 함수, 프로퍼티 등을 선언하면 코틀린에서 제공하는 4가지 접근 제한자별로 접근 제한 범위는 아래와 같이 적용됩니다.

public : (default) 어느 곳에서나 접근이 가능
private : 같은 파일 내에서만 접근 가능
internal : 같은 모듈 내에서만 접근 가능
protected : 최상위 레벨에서는 사용 불가능
val myData1: Int = 10
private val myData2: String = "hello"
class MyClass1() { }

private class MyClass2() { }

fun myFun1() {
    println("myFun1() call...")
}

private fun myFun2() {
    println("myFun2() call...")
}

fun main(args: Array<String>) {
    println("$myData1 .. ")
    println("$myData2 .. ")
    val obj1 = MyClass1()
    val obj2 = MyClass2()
    myFun1()
    myFun2()
}

접근 제한자별로 접근이 되는지 안되는지 확인해볼 수 있는 예시 코드입니다.

최상위 레벨에서 private는 같은 파일 내이기 때문에 fun main()역시 같은 파일이므로 문제 없이 실행이 됩니다.

 

클래스 멤버의 접근 범위

프로퍼티나 함수가 클래스 내부에 선언되었을 때, 최상위 레벨에서의 접근 제한과는 약간의 차이가 있습니다.

public : (default) 만약 접근 제한자를 명시하지 않으면 public 적용, 어느 곳이나 접근 가능
private : 같은 클래스 내에서만 접근 가능
internal : 같은 모듈에 선언된 클래스에서만 접근 가능
protected : private + 서브 클래스에서만 접근 가능 (private의 접근 범위에 서브 클래스가 추가된 것)
open class Super {
    val publicData: Int = 10
    protected val protectedData: Int = 10
    private val privateData: Int = 10
}

class Sub: Super() {
    fun visibilityTest() {
        println("$publicData .. ")
        println("$protectedData .. ")
        println("$privateData .. ")  // COMPILE ERROR
    }
}

class SomeClass {
    fun visibilityTest() {
        val obj = Super()
        println("${obj.publicData} .. ")
        println("${obj.protectedData} .. ")   // COMPILE ERROR
        println("${obj.privateData} .. ")    // COMPILE ERROR
    }
}

위 예시코드를 통해 public, protected, private 접근 제한자에 대해 정확히 알 수 있습니다.

 

프로퍼티와 생성자의 접근 제한

프로퍼티와 접근 제한자

프로퍼티는 변수처럼 사용되는 것이지만, getter와 setter를 포함하는 변수라는 의미입니다.

변수가 프로퍼티로 이용됨으로써 접근 제한자와 관련된 장점이 있습니다.

 

외부에서 내부의 프로퍼티에 접근은 허용하고 싶은데 내용의 변경은 허용하지 않도록 하고 싶은 경우가 있습니다.

이럴 경우에 프로퍼티의 접근 제한자로써 장점이 있습니다.

class PropertyVisibilityTest {
    private var data: Int = 10

    fun getData(): Int {
        return data;
    }
}

fun main(args: Array<String>) {
    val obj = PropertyVisibilityTest()
    println("${obj.getData()}")
}

외부에서의 접근은 허용하면서 내용의 변경은 막고 싶다면 다음과 같이 할 수 있겠죠.

해당 프로퍼티를 private로 선언(2번째 줄)
해당 프로퍼티를 반환하는 함수를 public 으로 선언(4번째 줄)

코틀린에서는 이러한 소스를 더 간결하게 getter와 setter를 이용해 작성할 수 있습니다.

class PropertyVisibilityTest {
    var data: Int = 10
        get() = field
        private set(value) {
            field = value
        }
}

fun main(args: Array<String>) {
    val obj = PropertyVisibilityTest()
    println("${obj.data}")
}

get에는 Public을 적용하고 set에는 private를 적용하였습니다. 이렇게 간단하게 적용할 수 있습니다.

위 소스에서 obj.data에 값을 대입하려 한다면 컴퍼일 에러가 날 것입니다.

 

생성자와 접근제한자

접근 제한자는 생성자에도 지정할 수 있습니다. 생성자는 객체가 생성될 때 호출되기 때문에 생성자에 접근 제한자를 지정한다는 의미는 해당 클래스의 객체 생성을 어느 범위까지 허용할 것인지를 나타냅니다. 예를 들어, 클래스의 접근 제한자가 public이면 어느 곳에서나 객체 생성이 가능하며, private이면 클래스 내부에서만 가능합니다. 주 생성자와 보조 생성자 모두 접근 제한자를 지정할 수 있습니다.

class ContructorVisibilityTest private constructor(name: String) {
    public constructor(name: String, no: Int): this(name) { }
}

생성자는 protected로 지정할 수 없습니다.

생성자에 접근 제한자를 지정하려면 생성자가 생략되더라도 constructor라는 키워드를 선언해주어야 합니다.

 

상속 관계와 접근제한자

클래스를 정의할 때 상속 관계에 의한 접근 제한자 지정에는 2가지 규칙이 존재합니다.

open과 private는 함께 사용할 수 없다.
하위 클래스에서 상위 멤버를 오버라이드할 때 접근 범위를 줄일 수 없다.
open class Super1 {
    open private fun myFun1() { // COMPILE ERROR
        
    }
    open fun myFun2() {
        
    }
    open protected fun myFun3() {
        
    }
}

class Sub1: Super1() {
    override private fun myFun2() { // COMPILE ERROR
        
    }
    
    override fun myFun3() {
        
    }
}

open와 private를 함께 사용하는 부분에서 다 컴퍼일 에러가 발생합니다.

두 번째는 왜 컴파일 에러가 났을까요? 하위 멤버가 상위 멤버로부터 상속을 받을 때에는 접근 권한을 축소할 수 없습니다.

위 코드를 보면 public으로 정의된 myFun2를 하위 클래스에서 private으로 축소하고 있습니다. 따라서 에러가 발생합니다.

 

 

이렇게 3개의 포스트를 통해 코틀린의 상속과 접근 제한자에 대해 살펴보았습니다.

다음 포스트는 코틀린에서의 추상 클래스와 인터페이스에 대해 알아보도록 하겠습니다.

반응형
LIST

'프로그래밍언어 > Kotlin' 카테고리의 다른 글

Kotlin 데이터 클래스  (0) 2019.08.09
Kotlin - 추상 클래스  (0) 2019.08.01
Kotlin 상속 (Kotlin Override) - 2  (0) 2019.07.28
Kotlin 상속 (Kotlin Override) - 1  (0) 2019.07.28
Kotlin에 대한 궁금증? (작성중)  (0) 2019.07.07
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함