songining

๋„๋ฉ”์ธ ํ”„๋กœํผํ‹ฐ ์ ‘๊ทผ ์ œ์–ด์ž

custom setter์™€ getter์˜ ์‚ฌ์šฉ

์ฝ”ํ‹€๋ฆฐ์—์„œ๋Š” ํ”„๋กœํผํ‹ฐ์— ๋Œ€ํ•œ getter์™€ setter๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์ง์ ‘ getter๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ๋ณด๋‹ค๋Š” ์•„๋ž˜ ์˜ˆ์‹œ์™€ ๊ฐ™์ด ์ฝ”ํ‹€๋ฆฐ์„ ์ข€ ๋” ์ฝ”ํ‹€๋ฆฐ์Šค๋Ÿฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

var stringRepresentation: String
    get() = this.toString()
    set(value) {
        setDataFromString(value) // parses the string and assigns values to other properties
    }

์—ฌ๊ธฐ์„œ ๋” ๋‚˜์•„๊ฐ€, ๋„๋ฉ”์ธ์— var ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ์™ธ๋ถ€์— ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ ์ง€์ ์ด ๋…ธ์ถœ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์™ธ๋ถ€์— ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ ์ง€์ ์„ ๋…ธ์ถœํ•˜๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๋ฉด private set ์„ ํ†ตํ•ด ํด๋ž˜์Šค ์™ธ๋ถ€์—์„œ ๋ณ€๊ฒฝํ•˜์ง€ ๋ชปํ•˜๋„๋ก ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค.

class Car(
    val name: String,
    position: Int = DEFAULT_POSITION,
    private val condition: MoveCondition = CarMoveCondition()
) {
    init {
        require(name.length <= 5) { "์ž๋™์ฐจ์˜ ์ด๋ฆ„์€ 5๊ธ€์ž๋ฅผ ๋„˜์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค." }
    }

    var position: Int = position
        private set
}

๋ฐฉ์–ด์  ๋ณต์‚ฌ

Cars ์ผ๊ธ‰ ์ปฌ๋ ‰์…˜์„ ๊ตฌํ˜„ํ•˜๋ฉฐ ๋ฆฌ๋ทฐ์–ด๋‹˜๊ป˜ Cars์˜ history ํ”„๋กœํผํ‹ฐ๋ฅผ ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋กœ ๋ฆฌํ„ดํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ›์•˜๋‹ค.

์—ฌ๊ธฐ์„œ ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ž€ ์ƒ์„ฑ์ž์˜ ์ธ์ž๋กœ ๋ฐ›์€ ๊ฐ์ฒด์˜ ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“ค์–ด ๋‚ด๋ถ€ ํ•„๋“œ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ฑฐ๋‚˜ getter๋ฉ”์„œ๋“œ์—์„œ ๋‚ด๋ถ€์˜ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋•Œ, ๊ฐ์ฒด์˜ ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“ค์–ด ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

Cars์˜ history ํ”„๋กœํผํ‹ฐ์˜ ๊ฒฝ์šฐ ๊ฒฝ์ฃผ ์ด๋ ฅ์„ ์ €์žฅํ•˜๋Š” ํ”„๋กœํผํ‹ฐ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ณผ๊ฑฐ ์ƒํƒœ๋ฅผ ๊ทธ๋•Œ ๊ทธ๋•Œ ์ €์žฅํ•ด์•ผํ•˜๋ฏ€๋กœ ๊ฐ’์„ ์ดˆ๊ธฐํ™” ๋˜๋Š” ๋ฐ˜ํ™˜ํ•  ๋•Œ ์ฃผ์†Œ ์ฐธ์กฐ๋ฅผ ๋Š์–ด์ฃผ์–ด์•ผ ํ•œ๋‹ค. (๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด Cars์˜ ์ƒํƒœ๊ฐ€ ๋ณ€ํ• ๋•Œ๋งˆ๋‹ค ์ด๋ ฅ๋„ ๊ฐ™์ด ๋ณ€ํ•จ)

class Cars(
    private val values: List<Car> = emptyList()
) {
    val history get() = values.map { it.copy() }

    fun race() {
        values.forEach {
            it.move()
        }
    }
}

์œ„์™€ ๊ฐ™์ด ์ž๋™์ฐจ ๊ฒฝ์ฃผ ์ด๋ ฅ์„ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด ๋ฐฉ์–ด์  ๋ณต์‚ฌ + ๊นŠ์€ ๋ณต์‚ฌ ๋ฅผ ์‚ฌ์šฉํ•ด history๋ฅผ backing property๋กœ ๊ตฌํ˜„ํ•ด์ฃผ์—ˆ๋‹ค.

์ฝ”ํ‹€๋ฆฐ์˜ map ์€ ์ƒˆ๋กœ์šด ๋ฆฌ์ŠคํŠธ๋กœ ๊ฐ์‹ธ์„œ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐฉ์–ด์  ๋ณต์‚ฌ ๊ธฐ๋Šฅ์„ ํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋Š” ๊นŠ์€ ๋ณต์‚ฌ๊ฐ€ ์•„๋‹ˆ๋‹ค. ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด์˜ ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“ค์—ˆ์–ด๋„, ๋‚ด๋ถ€ ์š”์†Œ๋“ค์˜ ์ฃผ์†Œ๋Š” ์›๋ณธ๊ณผ ๊ณต์œ ํ•˜๊ณ  ์žˆ๋‹ค.

Cars์˜ ๋‚ด๋ถ€ Car์˜ ์ƒํƒœ๋Š” ๊ณ„์†ํ•ด์„œ ๋ณ€ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— copy() ๋ฅผ ํ†ตํ•ด ๊นŠ์€ ๋ณต์‚ฌ๋ฅผ ํ•จ๊ป˜ ๊ฐ€์ ธ๊ฐ”๋‹ค.

๊ฐ์ฒด ๋‚ด๋ถ€์˜ ๊ฐ’์„ ์™ธ๋ถ€๋กœ๋ถ€ํ„ฐ ๋ณดํ˜ธํ•˜๊ณ  ์‹ถ์„ ๋•Œ๋Š” ์ปฌ๋ ‰์…˜์˜ ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ฅผ ๋น„๋กฏํ•ด ๋‚ด๋ถ€ ์š”์†Œ(Car)๋ฅผ ๋ถˆ๋ณ€ ๊ฐ์ฒด ๋˜๋Š” ๊นŠ์€ ๋ณต์‚ฌ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜์ž.

 

์ฐธ๊ณ 

https://tecoble.techcourse.co.kr/post/2021-04-26-defensive-copy-vs-unmodifiable/