코틀린에서 객체의 프로퍼티에 접근은 변수에 직접 접근하는 것이 아니라 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 |