Develop!/Kotlin

Property in kotlin

체리필터 2023. 8. 7. 15:48
728x90
반응형

Class 안에 있는 member 변수, 그리고 그 값을 get, set 하는 것과 관련하여 코틀린에서는 어떻게 처리되는지 확인할 수 있다.

class Default {
    var i: Int = 0
    get() {
        println("get ${field}")
        return field
    }
    set(value) {
        println("set(${value})")
        field = value
    }
}

fun defaultGetSet() {
    val d = Default()
    d.i = 2
    d.i
}

fun main() {
    defaultGetSet()
}

kotlin에서는 get, set을 할 때 Java처럼 getXXX 식으로 하는게 아니라 해당 멤버변수(프로퍼티) 아래에 get, set 함수를 작성해 주면 된다.

그리고 해당 멤버변수(프로퍼티)는 get, set 함수 내에서 field 라는 변수명으로 접근이 가능하다. 잘 몰랐는데 책에서도 get, set 함수는 한 번 들여쓰기 하던데... intellij에서 해 주는 자동완성에서도 들여쓰기를 해 주는 것을 볼 수 있다.

위와 같이 해 둔 상태에서 "d.i"에 값을 대입하면 자동으로 setter가 호출 되고, 그냥 단순 호출 또는 명시만 해 줘도 getter가 호출 된다.

get, set을 구현 안하게 되면 기본적인 get, set을 사용하게 된다.

class LogChange {
    var n: Int = 0
    set(value) {
        println("field becomes $value")
        field = value
    }
}

fun logChangeGetSet() {
    val lc = LogChange()
    lc.n
    lc.n = 2
}

lc.n을 단순 호출하면 getter가 호출 되는데 기본 getter가 호출 되기 때문에 아무런 증상이 없다.

하지만 "lc.n = 2"와 같이 setter가 만들어진 상태에서 호출을 하게 되면 다음과 같이 임의로 만든 setter가 호출 된 것을 볼 수 있다.

Getter, Setter를 private으로 정의해 두면 접근이 불가하다.

class Counter {
    var value: Int = 0
    private set
    fun inc() = value++
}

fun counterGetSet() {
    val counter = Counter()
    repeat(10) {
        counter.inc()
    }
    println(counter.value)
//    counter.value = 20
}

counter.inc()를 10번 반복해 주게 되면 value 값이 10이 되기 때문에 counter.value를 출력하면 10이 나온다. 이 때 선언되지 않은 getter를 사용하게 된다.

하지만 set은 private으로 선언되어 있으므로 "counter.value = 20"과 같은 코드는 에러를 내게 된다.

property는 실제 변수를 선언해서 값을 저장할 수도 있지만, 그 때 그 때 값을 계산해서 정의할 수도 있다.

class Hamster(val name: String) {
    override fun toString(): String {
        return "hamster's name : ${name}"
    }
}

class Cage(private val maxCapacity: Int) {
    private val hamsters = mutableListOf<Hamster>()

    val capacity: Int
        get() {
            return maxCapacity - hamsters.size
        }

    val full: Boolean
        get() {
            return hamsters.size == maxCapacity
        }

    fun put(hamster: Hamster): Boolean =
        if (full)
            false
        else {
            hamsters += hamster
            true
        }

    fun take(): Hamster = hamsters.removeAt(0)

    override fun toString(): String {
        return "capacity : ${capacity}, full : ${full}"
    }
}

fun hamsters() {
    val cage = Cage(2)
    println(cage.full)
    println(cage.capacity)

    println(cage.put(Hamster("Alice")))
    println(cage.put(Hamster("Bob")))
    println(cage)

    println(cage.full)
    println(cage.capacity)
    println(cage.put(Hamster("Charlie")))
    println(cage.take())
    println(cage.capacity)
}

Hamster라는 Class를 만들고 이름을 가지도록 한다.

Cage에서는 hamster를 List로 가지고 있는 hamsters 라는 property를 만들고 Cage에 얼마만큼의 Hamster를 가둘 수 있는지를 나타내는 capacity property, Cage가 꽉 찼는지를 나타내는 full 이라는 property를 만들었다.

capacity와 full 이라는 property는 maxCapacity와 hamsters의 size를 기반으로 계산해서 값을 돌려 준다.

이를 실행해 보면 아래와 같이 나오게 된다.

각각의 프로퍼티에 접근할 때 마다 값을 어떻게 계산해서 돌려주는지 확인해 볼 수 있다.

728x90
반응형

'Develop! > Kotlin' 카테고리의 다른 글

이름 붙은 인자, 가변인자 in kotlin  (0) 2023.08.16
확장함수 in kotlin  (0) 2023.08.14
Map in Kotlin  (0) 2023.08.04
Set in Kotlin  (0) 2023.08.02
가변인자 목록 in Kotlin  (0) 2023.08.02