Kotlin

backing field <custom getter(), setter() 설정>

kakaroo 2022. 3. 26. 00:42
반응형

article logo

 

코틀린에서 객체의 프로퍼티에 접근은 변수에 직접 접근하는 것이 아니라 Accessor 메소드(getter & setter)를 통해서 이루어집니다.

 

프로퍼티를 선언할 때 별도로 getter & setter 메소드를 구현하지 않으면 해당 속성은 디폴트로 정의된 메소드가 생략되어 있습니다.

여기서, 프로퍼티로 이용할 수 있는 변수는 어떤 블록 { } 에도 포함되지 않는 최상위 레벨 변수와 클래스 내부에 선언한 멤버 변수입니다. 최상위 레벨 변수에도 getter or setter 를 적용할 수 있다는 의미입니다.

이때, var은 변경 가능한 속성이기에 getter & setter 메소드를 가질 수 있고, val의 경우 변경 불가능한 속성이기에 setter 메소드 없이 getter 메소드만 가질 수 있습니다.

 

기본으로 제공되는 getter/setter 함수를 나만의 커스텀 setter/getter 함수로 표현한 예입니다.

var score = Score("Math", 50)
println(score.score)    //70
score.score = 30
println(score.score)    //70
println(score.isMin)    //true


class Score(val subject: String, _score: Int = MID_SCORE) {
    companion object {
        const val MIN_SCORE =   70
        const val MID_SCORE =   85
        const val MAX_SCORE =   100
    }

    var score = validScore(_score)  //객체 생성시 호출
        set(value) {                //property에 값을 변경할 때 호출
            field = validScore(value)   //field 식별자
        }

    val isMin: Boolean
        get() = this.score <= MIN_SCORE

    private fun validScore(s: Int) =
        s.coerceIn(MIN_SCORE, MAX_SCORE)
}

 

주 생성자의 매개변수에는 get(), set() 함수를 정의할 수가 없습니다.

하지만, 아래와 같이 주 생성자의 매개변수를 var 로 선언했기 때문에 외부에서 주 생성자의 매개변수를 접근할 수 있습니다.

class User2(var name:String) {
    var myName = name
        get() = field.uppercase()
        set(value) {
            field = "Hello " + value
        }
}

val user2 = User2("kkang")
user2.name = "Yoon"
println(user2.name + " " + user2.myName)	//Yoon KKANG

user2.myName = "Seol"
println(user2.name + " " + user2.myName)	//Yoon HELLO SEOL

주 생성자의 매개변수에 val 이나 var를 제거해서 외부에서 직접 접근할 수 없게 하며, 클래스의 프로퍼티 명과 매개변수명을 똑같이 작성하는 것이 정석입니다.

class User2(name:String) {
    var name = name
        get() = field.uppercase()
        set(value) {
            field = "Hello " + value
        }
}

 

외부에서 프로퍼티 값을 변경할 수는 없고, 읽어오고만 싶을 때는 private 접근 제한자를 사용해 아래와 같이 정의합니다.

class User {
	var age : Int = 10
            private set(value) {
                field = value
            }
}

val user = User()
user.age = 20	//error

get(), set()에 사용되는 접근 제한자(public > protected/internal > private)는 다음과 같은 규칙이 있습니다.

  • get() 함수의 접근 제한자는 프로퍼티의 접근 제한자와 항상 같다.
  • set() 함수의 접근 제한자는 프로퍼티의 접근 제한자와 다르게 설정할 수 있지만, 접근 범위를 넓혀서 설정할 수는 없다.

 


 

* field 식별자 ?

외부에서 프로퍼티를 이용할 때는 프로퍼티의 get(), set() 함수가 호출되지만, get(), set() 내부에서는 field 를 통해 프로퍼티가 가지고 있는 값에 접근합니다. 이렇게 뒤에 숨어있는 필드라는 의미라는 뜻으로 backing field 라고 부릅니다.

반응형

'Kotlin' 카테고리의 다른 글

lateinit, lazy  (0) 2022.03.26
Scope 함수(범위 지정 함수 - apply, with, let, also, run)  (0) 2022.03.26
val, const val  (0) 2022.03.25
람다, 고차함수, 함수합성, 클로저  (0) 2022.03.25
NewsFeed - JSoup / Nested RecyclerView  (0) 2022.03.16