๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“š Kotlin

[Effective Kotlin] ์•„์ดํ…œ 36. ์ƒ์†๋ณด๋‹ค๋Š” ์ปดํฌ์ง€์…˜์„ ์‚ฌ์šฉํ•˜๋ผ

by GroovyArea 2023. 1. 30.

[์ดํŽ™ํ‹ฐ๋ธŒ ์ž๋ฐ”] ๋ฅผ ์ฝ์—ˆ๋˜ ๊ธฐ์–ต์„ ๋– ์˜ฌ๋ ธ์„ ๋•Œ '์ƒ์†๋ณด๋‹ค๋Š” ์ปดํฌ์ง€์…˜์„ ์‚ฌ์šฉํ•˜๋ผ' ๋ผ๋Š” ์•„์ดํ…œ์ด ์ƒ๋‹นํžˆ ์ธ์ƒ ๊นŠ์—ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์ปดํฌ์ง€์…˜ ์ ์šฉ์‹œํ‚ค๋ฉด์„œ ๋‹คํ˜•์„ฑ์„ ๋งŒ์กฑ์‹œํ‚ค๋ ค๋ฉด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์† ๋ฐ›์•„์•ผ ํ•˜๋Š”๋ฐ, ๋ชจ๋‘ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋ฏ€๋กœ
์ฝ”๋“œ๊ฐ€ ์ฐธ ๋”๋Ÿฌ์›Œ์ง€๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

์ฝ”ํ‹€๋ฆฐ์„ ์ด๋ฅผ ๊ธฐ๊ฐ€ ๋ง‰ํžˆ๊ฒŒ ํ•ด๊ฒฐํ–ˆ๋‹ค.

๋‹ค์‹œ ์ƒ์†๊ณผ ์ปดํฌ์ง€์…˜์˜ ์˜ˆ๋ฅผ ์‚ดํŽด๋ณด๊ณ  ์ด๋ฅผ ์ฝ”ํ‹€๋ฆฐ์ด ์–ด๋–ป๊ฒŒ ๊ฐ„๋‹จํžˆ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์‚ดํŽด ๋ณด์ž.

 

์ƒ์†์˜ ๋ฌธ์ œ์ 

  • ๋ชจ๋“  ๊ฒƒ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜๋ฐ–์— ์—†์Œ
    • ์Šˆํผํด๋ž˜์Šค์˜ ์ƒํƒœ, ๋ฉ”์„œ๋“œ, ํ–‰์œ„ ๋“ฑ ๋ชจ๋“  ๊ฒƒ์„ ๊ฐ€์ ธ์˜จ๋‹ค.
      • ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ๋‚˜ํƒ€๋‚ผ ๋•Œ ๊ต‰์žฅํžˆ ์ข‹์€ ๋„๊ตฌ
    • ๊ทธ๋ ‡๊ธฐ์— ์ผ๋ถ€๋ถ„๋งŒ์„ ์‚ฌ์šฉํ•˜๊ธฐ์— ๋ถ€์ ํ•ฉํ•œ ๋ฐฉ๋ฒ•
    • ์ด๋ฅผ ์œ„ํ•ด์„œ ์ปดํฌ์ง€์…˜์„ ์‚ฌ์šฉํ•œ๋‹ค.
  • ์บก์Аํ™”๋ฅผ ๊นจ๋Š” ์ƒ์†
    • ๋‚ด๋ถ€์ ์ธ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์˜ ๋ณ€๊ฒฝ์œผ๋กœ ์บก์Аํ™”๊ฐ€ ๊นจ์ง„๋‹ค.

 

์ปดํฌ์ง€์…˜

์Šˆํผํด๋ž˜์Šค๋ฅผ ์ƒ์† ๋ฐ›๊ธฐ ๋ณด๋‹ค ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ์„ ์ทจํ•˜๊ธฐ ์œ„ํ•ด,
ํ”„๋กœํผํ‹ฐ๋กœ ์ทจํ•˜๋ฉด ๋œ๋‹ค.

์ด๋ฅผ ํ…Œ๋ฉด,

class CounterSet<T> : HashSet<T>() {

	//....
}

// ์œ„์˜ ํด๋ž˜์Šค์ฒ˜๋Ÿผ ์Šˆํผํด๋ž˜์Šค๋ฅผ ์ง์ ‘ ์ƒ์† ๋ฐ›๋Š” ๊ฒƒ์ด ์•„๋‹Œ,

class CounterSet<T> {
	private val innerSet = HashSet<T>()
    
    // ...
}

// ์ด๋Ÿฌํ•œ ํ˜•ํƒœ๋กœ ํ”„๋กœํผํ‹ฐ๋กœ ๊ฐ€์ ธ์™€์„œ ์ ์ ˆํžˆ ํ•„์š”ํ•œ ํ–‰์œ„๋งŒ ์‚ฌ์šฉํ•œ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด HashSet์˜ ๋ชจ๋“  ๊ฒƒ์„ ๊ฐ€์ ธ์˜ค๊ธฐ ๋ณด๋‹ค๋Š” CounterSet ๊ฐ์ฒด๊ฐ€ ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ์„ ์ปดํฌ์ง€์…˜์„ ํ†ตํ•ด ์–ป์€ innerSet ํ”„๋กœํผํ‹ฐ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

ํ•˜์ง€๋งŒ,
์ปดํฌ์ง€์…˜์„ ํ™œ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ๋‹คํ˜•์„ฑ์˜ ์ด์ ์„ ํ™œ์šฉํ•˜์ง€ ๋ชปํ•  ๊ฒฝ์šฐ๊ฐ€ ์ƒ๊ธด๋‹ค.

์ด๋Ÿด ๊ฒฝ์šฐ์—๋Š” ํฌ์›Œ๋”ฉ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๊ทน๋ณตํ•  ์ˆ˜ ์žˆ๋‹ค.

class CounterSet<T> : MutableSet<T>{
	private val innerSet = HashSet<T> ()
    
    //,..
    
    // ํ•˜์ง€๋งŒ MutableSet ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ชจ๋“  ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ innerSet์„ ์ด์šฉํ•˜์—ฌ ์˜ค๋ฒ„๋ผ์ด๋“œ ํ•ด์•ผ ํ•œ๋‹ค.
    // ๊ฐœ๊ท€์ฐฎ.. ์ฝ”๋“œ ๊ฐœ๋”๋Ÿฝ..
}

์ฝ”๋“œ๊ฐ€ ํ•„์š” ์ด์ƒ์œผ๋กœ ๊ธธ์–ด์ง€๋ฏ€๋กœ ์ฃผ์„๋งŒ ์ž‘์„ฑํ–ˆ๋‹ค.
MutableSet์˜ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๊ฐ€ ์–ผ๋งˆ๋‚˜ ๋งŽ์€๋ฐ, ๊ทธ๊ฑธ ์–ด๋–ป๊ฒŒ ๋‹ค ๊ตฌํ˜„ํ• ๊นŒ?
์ฝ”๋“œ๊ฐ€ ํ•„์š” ์ด์ƒ์œผ๋กœ ๋„ˆ๋ฌด ๊ธธ์–ด์ง„๋‹ค. (์ž๊ทธ๋งˆ์น˜ 9๊ฐœ..)

์ฝ”ํ‹€๋ฆฐ์„ ์ด๋ฅผ Fancy ํ•˜๊ฒŒ ํ•ด๊ฒฐํ–ˆ๋‹ค.
๋ฐ”๋กœ ์œ„์ž„ ํŒจํ„ด์„ ํ†ตํ•ด์„œ.

class CounterSet<T> (
	private val innerSet = HashSet<T>(),
) : MutableSet<T> by innerSet {
	
    //...
    
    // ์ด์ œ๋Š” by ํ‚ค์›Œ๋“œ๋กœ ์ธํ•ด ํ”„๋กœํผํ‹ฐ์ธ innerSet์„ ์ด์šฉํ•ด ๊ตฌํ˜„์„ ์œ„์ž„ํ•  ์ˆ˜ ์žˆ๋‹ค.
    // by ํ‚ค์›Œ๋“œ ํ•˜๋‚˜๋กœ..!
}

์ฐธ Fancy ํ•˜๋‹ค.

์ •๋ฆฌ

ํ•˜์ง€๋งŒ ๋‹คํ˜•์„ฑ๊นŒ์ง€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ๊ฐ€ ๊ฑฐ์˜ ์—†์„ ๊ฒƒ์ด๋‹ค.
์›ฌ๋งŒํ•œ ๊ฒฝ์šฐ๋Š” ์ปดํฌ์ง€์…˜์œผ๋กœ ํ•ด๊ฒฐํ•  ์ผ์ด ๋งŽ์„ ๊ฒƒ์ด๋‹ค.

์ปดํฌ์ง€์…˜์„ ํ™œ์šฉํ•˜๋ฉด, ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šฐ๋ฉฐ, ์œ ์—ฐํ•˜๊ฒŒ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.
๊ตณ์ด ๋‹คํ˜•์„ฑ์„ ๊ฐ€์ ธ๊ฐ€๊ธฐ ์œ„ํ•ด ์œ„์ž„์„ ์‚ฌ์šฉํ•  ํ•„์š” ์—†์ด.

์ƒ์†์„ ํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ํ•˜๋ ค๋ฉด final ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

ํ•˜์ง€๋งŒ ์ƒ์†ํ•˜๋ ค๋Š” ํด๋ž˜์Šค์˜ ํŠน์ • ๋ฉ”์„œ๋“œ๋“ค์˜ ์˜ค๋ฒ„๋ผ์ด๋”ฉ์„ ๋ง‰์œผ๋ ค๋ฉด open ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์ด์ง€ ์•Š์œผ๋ฉด ๋œ๋‹ค.
์ฝ”ํ‹€๋ฆฐ์€ ์ฐธ ๊ฐ„๋‹จํ•˜๋‹ค. (๋ฌผ๋ก  ์ด๊ฑด ์ž๋ฐ”์™€ ๋น„์Šทํ•˜์ง€๋งŒ)

๋งˆ์ง€๋ง‰์œผ๋กœ OOP ์ง€ํ–ฅ ๋ฐฉ๋ฒ•์€ ์ƒ์†๋ณด๋‹ค๋Š” ์ปดํฌ์ง€์…˜ ์‚ฌ์šฉ์ด best๋ผ๋Š” ์ ์„ ์ธ์ง€ํ•˜๋ฉด์„œ ๋งˆ๋ฌด๋ฆฌํ•œ๋‹ค.

๋ฐ˜์‘ํ˜•