๐Ÿค” ์ž๋ฐ” ๊ธฐ์ดˆ ๋ฐฐ์šธ ๋•Œ ์•ž์ชฝ์— ๋‚˜์˜ค๋Š” ์ƒ์† ์™œ ํ˜„์—…์—์„œ๋Š” ์ž˜ ์•ˆ์“ด๋‹ค๊ณ  ํ•˜๋Š” ๊ฑธ๊นŒ? (feat. ์ฝ”ํ‹€๋ฆฐ์—์„œ ์ƒ์†์€?)

GoldenDuskยท2024๋…„ 10์›” 17์ผ
8

effective-java

๋ชฉ๋ก ๋ณด๊ธฐ
4/5

์ดํŽ™ํ‹ฐ๋ธŒ ์ž๋ฐ” ์Šคํ„ฐ๋””๋ฅผ 9์›”๋ถ€ํ„ฐ ํ•˜๊ณ  ์žˆ๋Š” ์ค‘์ธ๋ฐ ์ €๋ฒˆ์ฃผ ์ฃผ์ œ ์ค‘์— ์ƒ์†์„ ์•„๋ฌด๋•Œ๋‚˜ ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ  ์ฃผ์˜ํ•ด์„œ ์‚ฌ์šฉํ•˜๋ผ๋ผ๋Š” ์ฃผ์ œ๊ฐ€ ๋‚˜์™”์—ˆ๋‹ค.. ๊ทผ๋ฐ ์ฃผ์˜์ ์ด ๋„ˆ๋ฌด ๋งŽ์•„์„œ ๊ทธ๋Ÿฌ๋ฉด ์ƒ์†์„ ์•ˆ์“ฐ๋ฉด ๋˜๋Š” ๊ฑฐ ์•„๋‹Œ๊ฐ€์š”? ํ•˜๋Š” ๋ง์ด ๋‚˜์™”์—ˆ์Œ ์Šคํ„ฐ๋””์›์ด ์ •๋ฆฌํ•œ ๊ฒƒ ์ค‘์— ์•„๋ž˜์™€ ๊ฐ™์€ ๊ธ€๋„ ์žˆ์—ˆ๋‹ค.

๐Ÿ’ฌ Java์˜ ์ฐฝ์‹œ์ž์ธ ์ œ์ž„์Šค ๊ณ ์Šฌ๋ง(James Arthur Gosling)์ด ํ•œ ์ธํ„ฐ๋ทฐ์—์„œ "๋‚ด๊ฐ€ ์ž๋ฐ”๋ฅผ ๋งŒ๋“ค๋ฉด์„œ ๊ฐ€์žฅ ํ›„ํšŒํ•˜๋Š” ์ผ์€ ์ƒ์†์„ ๋งŒ๋“  ์ ์ด๋‹ค"๋ผ๊ณ  ๋งํ–ˆ๋‹ค.

์กฐ์Šˆ์•ผ ๋ธ”๋กœํฌ์˜ Effective Java์—์„œ๋Š” ์ƒ์†์„ ์œ„ํ•œ ์„ค๊ณ„์™€ ๋ฌธ์„œ๋ฅผ ๊ฐ–์ถ”๊ฑฐ๋‚˜, ๊ทธ๋Ÿด ์ˆ˜ ์—†๋‹ค๋ฉด ์ƒ์†์„ ๊ธˆ์ง€ํ•˜๋ผ๋Š” ์กฐ์–ธ์„ ํ•œ๋‹ค.
๋”ฐ๋ผ์„œ ์ถ”์ƒํ™”๊ฐ€ ํ•„์š”ํ•˜๋ฉด ์ธํ„ฐํŽ˜์ด์Šค๋กœ implements ํ•˜๊ฑฐ๋‚˜ ๊ฐ์ฒด ์ง€ํ–ฅ ์„ค๊ณ„๋ฅผ ํ• ๋• ํ•ฉ์„ฑ(composition)์„ ์ด์šฉํ•˜๋Š” ๊ฒƒ์ด ์ถ”์„ธ์ด๋‹ค.

ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๊ฐ€ ๊ธฐ์ดˆ๋ฅผ ๋ฐฐ์šธ ๋•Œ๋Š” ํ•ญ์ƒ ์ƒ์†์„ ๋งŽ์ด ๋ฐฐ์šฐ๊ธฐ๋„ ํ•˜๊ณ  ํ•ด์„œ ๊ถ๊ธˆํ•ด์กŒ๋‹ค! ๊ทธ๋ฆฌ๊ณ  ์ฝ”ํ‹€๋ฆฐ์ด ์ž๋ฐ”์—์„œ์˜ ๋ถˆํŽธํ•œ ์ ์„ ๊ฑฐ์˜ ๋งŽ์ด ๊ฐœ์„ ํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์ธ๋ฐ ์ด๋Ÿฌํ•œ ์ ๋„ ๊ฐœ์„ ๋˜์—ˆ๋Š”์ง€ ์•Œ์•„๋ณด๊ณ ์ž ํ•จ

์ข€ ๋” ๋”ฅํ•˜๊ฒŒ ์ƒ์†์„ ์“ฐ๊ฒŒ ๋˜๋ฉด,

  • ๋ฌด์—‡์ด ๋ฌธ์ œ์ธ์ง€
  • ์™œ ๋ฌธ์ œ์ธ์ง€
  • ๊ทธ๋ ‡๋‹ค๋ฉด ์ •ํ™•ํžˆ ์–ธ์ œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฑด์ง€ ์•Œ์•„๋ณด์ž..
  • ์ดํŽ™ํ‹ฐ๋ธŒ ์ž๋ฐ”์™€ ํ•จ๊ป˜ ๊ทธ๋ฆฌ๊ณ  ์ฝ”ํ‹€๋ฆฐ์—์„œ ์ƒ์†์ด ์—†๋Š”๊ฐ€๋„ ์•Œ์•„๋ณด์ž

ํšŒ์‚ฌ ์ฝ”๋“œ๊ฐ€ ์ •๋‹ต์€ ์•„๋‹ˆ์ง€๋งŒ ํšŒ์‚ฌ ์ฝ”๋“œ ๋˜ํ•œ ์‚ดํŽด๋ณด์•˜๋‹ค! ์ผ๋‹จ ์ƒ์†์ด ๋ฌด์—‡์ธ์ง€์™€ ์ดํŽ™ํ‹ฐ๋ธŒ ์ž๋ฐ”์—์„œ ๋Œ€์•ˆ์„ ์•Œ์•„๋ณด์ž

1. ์ƒ์†(Inheritance)

์ผ๋ฐ˜์ ์ธ ๊ตฌ์ฒด ํด๋ž˜์Šค๋ฅผ ํŒจํ‚ค์ง€ ๊ฒฝ๊ณ„๋ฅผ ๋„˜์–ด, ์ฆ‰ ๋‹ค๋ฅธ ํŒจํ‚ค์ง€์˜ ๊ตฌ์ฒด ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•˜๋Š” ์ผ์€ ์œ„ํ—˜ํ•˜๋‹ค. ์ƒ๊ธฐํ•˜์ž๋ฉด, ์ด ์ฑ…์—์„œ์˜ โ€˜์ƒ์†โ€™์€ ํด๋ž˜์Šค๊ฐ€ ๋‹ค๋ฅธ ํด๋ž˜์Šค๋ฅผ ํ™•์žฅํ•˜๋Š” ๊ตฌํ˜„ ์ƒ์†์„ ๋งํ•œ๋‹ค. ์ด๋ฒˆ ์•„์ดํ…œ ์—์„œ ๋…ผํ•˜๋Š” ๋ฌธ์ œ๋Š” ํด๋ž˜์Šค๊ฐ€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ฑฐ๋‚˜ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋‹ค๋ฅธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™•์žฅํ•˜๋Š” ์ธํ„ฐ ํŽ˜์ด์Šค ์ƒ์†๊ณผ๋Š” ๋ฌด๊ด€ํ•˜๋‹ค.

1) ์ƒ์†์ด๋ž€

์ƒ์†์€ ๊ฐ์ฒด ์ง€ํ–ฅ 4๊ฐ€์ง€ ํŠน์ง•์ค‘ ํ•˜๋‚˜๋กœ์„œ ํด๋ž˜์Šค ๊ธฐ๋ฐ˜์˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ๋ฐฐ์šฐ๋Š” ๊ฐœ๋…์ด๋‹ค.

ํด๋ž˜์Šค ์ƒ์†์„ ํ†ตํ•ด ์ž์‹ ํด๋ž˜์Šค๋Š” ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ์ž์›์„ ๋ฌผ๋ ค ๋ฐ›๊ฒŒ ๋˜๋ฉฐ, ๋ถ€๋ชจ ํด๋ž˜์Šค์™€ ๋‹ค๋ฅธ ๋ถ€๋ถ„๋งŒ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์žฌ์ •์˜ํ•จ์œผ๋กœ์จ ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ์‰ฝ๊ฒŒ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.
๊ทธ๋ž˜์„œ ์ƒ์† ๊ด€๊ณ„๋ฅผ is-a ๊ด€๊ณ„๋ผ๋„ ํ‘œํ˜„ํ•˜๊ธฐ๋„ ํ•œ๋‹ค.

is-a๋Š” ์ผ์ข…์˜ ~์ด๋‹ค๋ผ๋Š” ์˜๋ฏธ์ด๋‹ค.

์ถœ์ฒ˜ : https://itwiki.kr/w/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4_ISA_%EA%B4%80%EA%B3%84

class Mobile {
	// ...
}

class Apple extends Mobile {
	// ...
}

๐Ÿ”Ž ์„œ๋ธŒ ํด๋ž˜์‹ฑ๊ณผ ์„œ๋ธŒ ํƒ€์ดํ•‘

์ƒ์†์˜ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๊ฐ์ฒด์ง€ํ–ฅ์˜ ์‚ฌ์‹ค๊ณผ ์˜คํ•ด์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค๋ช…ํ•œ๋‹ค๊ณ  ํ•จ.

๐Ÿ’ฌ ์ƒ์†์€ ์„œ๋ธŒํƒ€์ดํ•‘(subtyping)๊ณผ ์„œ๋ธŒํด๋ž˜์‹ฑ(subclassing)์˜ ๋‘ ๊ฐ€์ง€ ์šฉ๋„๋กœ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋‹ค.

์„œ๋ธŒํด๋ž˜์Šค๊ฐ€ ์Šˆํผํด๋ž˜์Šค๋ฅผ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ ์ด๋ฅผ ์„œ๋ธŒํƒ€์ดํ•‘์ด๋ผ๊ณ  ํ•œ๋‹ค. ์„œ๋ธŒํด๋ž˜์Šค๊ฐ€ ์Šˆํผํด๋ž˜์Šค๋ฅผ ๋Œ€์ฒดํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ์—๋Š” ์„œ๋ธŒํด๋ž˜์‹ฑ์ด๋ผ๊ณ  ํ•œ๋‹ค. ์„œ๋ธŒํƒ€์ดํ•‘์€ ์„ค๊ณ„์˜ ์œ ์—ฐ์„ฑ์ด ๋ชฉํ‘œ์ธ ๋ฐ˜๋ฉด ์„œ๋ธŒํด๋ž˜์‹ฑ์€ ์ฝ”๋“œ์˜ ์ค‘๋ณต ์ œ๊ฑฐ์™€ ์žฌ์‚ฌ์šฉ์ด ๋ชฉ์ ์ด๋‹ค.

์—„๋ฐ€ํžˆ ๋งํ•˜๋ฉด ์ƒ์†์€ ๊ทธ์ € ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ ์œ„ํ•œ ๊ธฐ๋ฒ•์ด ์•„๋‹ˆ๋‹ค?

[์ƒ์†์„ ํ†ตํ•œ ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ]
์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์ด๋ž€ ๋ฌด์—‡์ผ๊นŒ? ์• ์ดˆ์— ์šฐ๋ฆฌ๊ฐ€ ํ•จ์ˆ˜(function)์„ ๋งŒ๋“ค์–ด ์“ฐ๋Š” ์ด์œ ๊ฐ€ ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์ฝ”๋“œ๋ฅผ ๋ฌถ์–ด ์žฌ์‚ฌ์šฉ์„ ํ†ตํ•ด ์ฝ”๋“œ ์ค‘๋ณต์„ ์ค„์ด๊ธฐ ์œ„ํ•ด์„œ์ด๋‹ค. ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์ฝ”๋“œ๊ฐ€ ์žˆ๋‹ค๋ฉด, ๋ถ€๋ชจ ํด๋ž˜์Šค์— ๋ฉ”์†Œ๋“œ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด๋†“๊ณ  ์ƒ์†์„ ํ†ตํ•ด ๋ถ€๋ชจ์˜ ๊ฒƒ์„ ๊ฐ€์ ธ์™€ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ธฐ๋ฒ•์œผ๋กœ ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์ด๋ผ๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๋‹ค๋งŒ, ์—„๋ฐ€ํžˆ ๋งํ•˜๋ฉด ์ƒ์†์€ ๊ทธ์ € ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ ์œ„ํ•œ ๊ธฐ๋ฒ•์ด ์•„๋‹ˆ๋ผ๊ณ  ํ•œ๋‹ค.

์ผ๋ฐ˜์ ์ธ ํด๋ž˜์Šค๊ฐ€ ์ด๋ฏธ ๊ตฌํ˜„์ด ๋˜์–ด ์žˆ๋Š” ์ƒํƒœ์—์„œ ๊ทธ๋ณด๋‹ค ์ข€ ๋” ๊ตฌ์ฒด์ ์ธ ํด๋ž˜์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ๊ธฐ๋ฒ•์ด๋ฉฐ, ๊ทธ๋กœ ์ธํ•ด ์ƒ์œ„ ํด๋ž˜์Šค์˜ ์ฝ”๋“œ๋ฅผ ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ์žฌ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ์„ ๋ฟ์ด๋‹ค.

์ด์ฒ˜๋Ÿผ '์‚ฌ๋žŒ' ์ด๋ผ๋Š” ๊ฐ์ฒด ์ฃผ์ œ๋Š” ๊ฐ™์ง€๋งŒ, ์ค‘ํ•™์ƒ, ๊ณ ๋“ฑํ•™์ƒ ์ฒ˜๋Ÿผ ์„œ๋กœ ๋‹ค๋ฅธ ์†์„ฑ์ด๋‚˜ ๊ธฐ๋Šฅ๋“ค์„ ๊ฐ€์ง€๊ณ  ์žˆ์„๋•Œ, ์ด๋Ÿฌํ•œ ๊ตฌ์กฐ๋ฅผ ์ƒ์† ๊ด€๊ณ„๋ฅผ ํ†ตํ•ด ๋…ผ๋ฆฌ์ ์œผ๋กœ ๊ฐœ๋…์ ์œผ๋กœ ์—ฐ๊ด€ ์‹œํ‚ค๋Š” ๊ฒƒ์„ ์ƒ์†์ด๋ผ ํ•œ๋‹ค.

ํด๋ž˜์Šค ํญ๋ฐœ ๐Ÿ”ฅ ๋ฌธ์ œ

์ƒ์† ๊ด€๊ณ„๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„์— ๊ฒฐ์ •๋˜๊ณ  ๊ณ ์ •๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋„์ค‘์— ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค. ๋”ฐ๋ผ์„œ ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ์„ ์กฐํ•ฉํ•ด์•ผ ํ•˜๋Š” ์„ค๊ณ„์— ์ƒ์†์„ ์ด์šฉํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ๋ชจ๋“  ์กฐํ•ฉ๋ณ„๋กœ ํด๋ž˜์Šค๋ฅผ ํ•˜๋‚˜ํ•˜๋‚˜ ์ถ”๊ฐ€ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.
์ด๊ฒƒ์„ ํด๋ž˜์Šค ํญ๋ฐœ ๋ฌธ์ œ๋ผ ํ•œ๋‹ค.

๋”๊ตฐ๋‹ค๋‚˜ Java8๋ถ€ํ„ฐ๋Š” ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋””ํดํŠธ ๋ฉ”์†Œ๋“œ ๊ธฐ๋Šฅ์ด ๋‚˜์˜ค๋ฉด์„œ ์ธํ„ฐํŽ˜์ด์Šค๋‚ด์—์„œ ๋กœ์ง ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•˜์—ฌ ์ƒ์†์˜ ์žฅ์ ์ด ์•ฝํ™”๋˜์—ˆ๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.

2) ์ƒ์†์˜ ๋‹ค์‚ฌ๋‹ค๋‚œ ๋ฌธ์ œ์ 

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

ํ•˜์ง€๋งŒ ํ˜„์—…, ์ดํŽ™ํ‹ฐ๋ธŒ ์ž๋ฐ” ๋“ฑ์—์„œ extends๋ฅผ ์ง€์–‘ํ•˜๋Š” ํŽธ์ด๋ฉฐ ํด๋ž˜์Šค ์ƒ์†์„ ํ•ด์•ผํ• ๋•Œ๋Š” ์ •๋ง ๊ฐœ๋…์ ์œผ๋กœ ์—ฐ๊ด€ ๊ด€๊ณ„๊ฐ€ ์žˆ์„ ๋•Œ๋งŒ ํ•˜๋Š” ์ƒ๋‹นํžˆ ์ œํ•œ์ ์œผ๋กœ ์„ ํƒ์ ์œผ๋กœ ๋‹ค๋ค„์ง„๋‹ค.

๐Ÿ”‘ ๋ฌธ์ œ์  1 : ๋ถˆํ•„์š”ํ•œ ๊ธฐ๋Šฅ ์ƒ์†

์„œ๋ธŒ ํด๋ž˜์‹ฑ์ด๋ž€ ๊ด€์ ์—์„œ ๋ณธ ์ƒ์†์˜ ๋ฌธ์ œ์ ์œผ๋กœ ์„œ๋ธŒํด๋ž˜์‹ฑ์ด๋ž€ ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ ๋ชฉ์ ์˜ ์ƒ์†

๋‹ค์Œ์€ ์ด๋ฏธ ์•ˆ์ •์ ์œผ๋กœ ๊ตฌํ˜„๋œ CircularBuffer ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•˜์—ฌ CircularQueue์™€ CircularStack์„ ๊ตฌํ˜„ํ•˜๊ณ ์ž ํ•˜๋Š” ์˜ˆ์‹œ์ด๋‹ค. ์ด ์ฝ”๋“œ์—์„œ ์ƒ์†์„ ํ†ตํ•ด ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‹ค์Œ์€ Stack๊ณผ Queue ํด๋ž˜์Šค๊ฐ€ List ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์„ ๋•Œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™(Liskov Substitution Principle, LSP) ์œ„๋ฐ˜ ๋ฌธ์ œ๋ฅผ ๋‹ค๋ฃฌ ์˜ˆ์‹œ๋ฅผ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

List ํด๋ž˜์Šค ์ •์˜

์šฐ๋ฆฌ๋Š” List ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐฐ์—ด์ฒ˜๋Ÿผ ์ €์žฅํ•˜๊ณ , ์™ผ์ชฝ์ด๋‚˜ ์˜ค๋ฅธ์ชฝ์— ๊ฐ’์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋“ค์„ ์ œ๊ณตํ•œ๋‹ค.

public class List {
    private int[] elements;

    // ๋งจ ์ฒ˜์Œ์— ์š”์†Œ ์ถ”๊ฐ€
    public void pushLeft(int value) {
        // ๊ตฌํ˜„ ์ƒ๋žต
    }

    // ๋งจ ๋์— ์š”์†Œ ์ถ”๊ฐ€
    public void push(int value) {
        // ๊ตฌํ˜„ ์ƒ๋žต
    }

    // ์ฒซ ๋ฒˆ์งธ ์š”์†Œ ์ œ๊ฑฐ ํ›„ ๋ฐ˜ํ™˜
    public int popLeft() {
        // ๊ตฌํ˜„ ์ƒ๋žต
        return 0; // ์ž„์‹œ ๋ฐ˜ํ™˜๊ฐ’
    }

    // ๋งˆ์ง€๋ง‰ ์š”์†Œ ์ œ๊ฑฐ ํ›„ ๋ฐ˜ํ™˜
    public int pop() {
        // ๊ตฌํ˜„ ์ƒ๋žต
        return 0; // ์ž„์‹œ ๋ฐ˜ํ™˜๊ฐ’
    }
}

์ด List ํด๋ž˜์Šค๋Š” ์ด๋ฏธ ์•ˆ์ •์ ์œผ๋กœ ๊ตฌํ˜„๋œ ์ƒํƒœ๋กœ, ์ด์ œ ์ด ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์•„ ์Šคํƒ๊ณผ ํ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ๊ตฌํ˜„ํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

Stack๊ณผ Queue ํด๋ž˜์Šค ์ƒ์†

Stack๊ณผ Queue ํด๋ž˜์Šค๋Š” List ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์•„ ๊ฐ๊ฐ ์Šคํƒ๊ณผ ํ ์ž๋ฃŒ๊ตฌ์กฐ๋กœ ๋™์ž‘ํ•˜๋„๋ก ๊ตฌํ˜„

public class Stack extends List {}

public class Queue extends List {}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Stack๊ณผ Queue๋Š” List์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์†๋ฐ›์•„ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Stack ์‚ฌ์šฉ ์˜ˆ์‹œ

์Šคํƒ์€ ํ›„์ž…์„ ์ถœ(FILO) ํŠน์„ฑ์„ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด push์™€ pop ๋ฉ”์„œ๋“œ๋งŒ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

Stack stack = new Stack();
stack.push(1);  // [1]
stack.push(2);  // [1, 2]
stack.push(3);  // [1, 2, 3]
stack.pop();    // [1, 2] => 3 ๋ฐ˜ํ™˜
stack.push(4);  // [1, 2, 4]
stack.pop();    // [1, 2] => 4 ๋ฐ˜ํ™˜

Queue ์‚ฌ์šฉ ์˜ˆ์‹œ

ํ๋Š” ์„ ์ž…์„ ์ถœ(FIFO) ํŠน์„ฑ์„ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด push์™€ popLeft ๋ฉ”์„œ๋“œ๋งŒ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

Queue queue = new Queue();
queue.push(1);    // [1]
queue.push(2);    // [1, 2]
queue.push(3);    // [1, 2, 3]
queue.popLeft();  // [2, 3] => 1 ๋ฐ˜ํ™˜
queue.push(4);    // [2, 3, 4]
queue.popLeft();  // [3, 4] => 2 ๋ฐ˜ํ™˜

๐Ÿšจ ๋ฌธ์ œ์ : ์ƒ์œ„ ํด๋ž˜์Šค(๋ถ€๋ชจ ํด๋ž˜์Šค)๋ฅผ ์ƒ์†๋ฐ›์€ ํ•˜์œ„ ํด๋ž˜์Šค(์ž์‹ ํด๋ž˜์Šค)๋Š” ์ƒ์œ„ ํด๋ž˜์Šค์—์„œ ๊ธฐ๋Œ€ํ•˜๋Š” ๋™์ž‘์„ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์›์น™์ธ ๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™ ์œ„๋ฐฐ

Stack๊ณผ Queue๋Š” List์ฒ˜๋Ÿผ ์‚ฌ์šฉ๋˜๋”๋ผ๋„ ๋ฌธ์ œ๊ฐ€ ์—†์–ด์•ผ ํ•œ๋‹ค. Stack๊ณผ Queue๊ฐ€ List๋ฅผ ์ƒ์†๋ฐ›์•˜์œผ๋ฏ€๋กœ, ๊ฐ ํด๋ž˜์Šค๋Š” ๋ฌธ๋ฒ•์ ์œผ๋กœ List ํƒ€์ž…์œผ๋กœ ๋‹ค๋ค„์งˆ ์ˆ˜ ์žˆ๋‹ค.

List stack = new Stack();
List queue = new Queue();

๊ทธ๋Ÿฌ๋‚˜ List์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์†๋ฐ›์€ Stack๊ณผ Queue๋Š” ๋ณธ๋ž˜ ์ œ๊ณตํ•˜์ง€ ์•Š์•„์•ผ ํ•  ๋ฉ”์„œ๋“œ๋“ค ์ฆ‰, ๋ถˆํ•„์š”ํ•œ ๋ฉ”์„œ๋“œ๋“ค(pushLeft, popLeft ๋“ฑ)๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค. ์ด๊ฒƒ์€ ๊ฐ๊ฐ์˜ ์ž๋ฃŒ๊ตฌ์กฐ์˜ ๊ธฐ๋ณธ ํŠน์„ฑ์„ ๊นจ๋œจ๋ฆด ์ˆ˜ ์žˆ๋‹ค.

์Šคํƒ ๊ฐ์ฒด์—์„œ pushLeft๋‚˜ popLeft๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, ํ›„์ž…์„ ์ถœ(FILO) ํŠน์„ฑ์ด ๊นจ์ง„๋‹ค.

List stack = new Stack();
stack.push(1);    // [1]
stack.push(2);    // [1, 2]
stack.push(3);    // [1, 2, 3]
stack.pushLeft(4);  // [4, 1, 2, 3] - ์ˆœ์„œ๊ฐ€ ๊นจ์ง
stack.pop();        // [4, 1, 2] => 3 ๋ฐ˜ํ™˜
stack.popLeft();    // [1, 2] => 4 ๋ฐ˜ํ™˜

ํ ๊ฐ์ฒด์—์„œ๋„ pushLeft๋‚˜ pop์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, ์„ ์ž…์„ ์ถœ(FIFO) ํŠน์„ฑ์ด ๊นจ์ง„๋‹ค.

List queue = new Queue();
queue.push(1);    // [1]
queue.push(2);    // [1, 2]
queue.push(3);    // [1, 2, 3]
queue.pushLeft(4);  // [4, 1, 2, 3] - ์ˆœ์„œ๊ฐ€ ๊นจ์ง
queue.pop();        // [4, 1, 2] => 3 ๋ฐ˜ํ™˜
queue.popLeft();    // [1, 2] => 4 ๋ฐ˜ํ™˜
  • Stack์€ ํ›„์ž…์„ ์ถœ(LIFO) ๊ตฌ์กฐ๋ฅผ ๋”ฐ๋ฅด๋ฉฐ, ๋งˆ์ง€๋ง‰์— ์ถ”๊ฐ€๋œ ์š”์†Œ๋ฅผ ์ œ๊ฑฐํ•ด์•ผ ํ•œ๋‹ค.
  • Queue๋Š” ์„ ์ž…์„ ์ถœ(FIFO) ๊ตฌ์กฐ๋ฅผ ๋”ฐ๋ฅด๋ฉฐ, ๋จผ์ € ์ถ”๊ฐ€๋œ ์š”์†Œ๋ฅผ ๋จผ์ € ์ œ๊ฑฐํ•ด์•ผ ํ•ฉํ•œ๋‹ค.

์ด๋Š” ๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™์„ ์œ„๋ฐฐํ•˜๋Š” ์‚ฌ๋ก€๋กœ, ์ฝ”๋“œ์˜ ์œ ์ง€๋ณด์ˆ˜์„ฑ๊ณผ ๊ฐ€๋…์„ฑ์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“ข ์ฆ‰, ์„œ๋ธŒ ํด๋ž˜์‹ฑ ๊ด€์ ์˜ ์ƒ์†์€ ํƒ€์ž…๋“ค ์‚ฌ์ด์˜ ๊ด€๊ณ„์— ๋Œ€ํ•œ ๊ณ ๋ ค ์—†์ด ์˜ค๋กœ์ง€ ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ๋งŒ์„ ๋ชฉ์ ์œผ๋กœ ์ƒ์†์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ์ด๋‹ค.

์ƒ์†์œผ๋กœ ์ธํ•ด Stack๊ณผ Queue์— ํ˜ธ์ถœ๋˜์–ด์„œ๋Š” ์•ˆ๋˜๋Š” ๋ฉ”์„œ๋“œ๋“ค์ด ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์ƒ๊ฒจ๋‚ฌ๊ธฐ ๋•Œ๋ฌธ์—, ์ •ํ™•ํžˆ ๋งํ•˜๋ฉด Stack๊ณผ Queue ํƒ€์ž…์— ๋ถˆํ•„์š”ํ•œ ํผ๋ธ”๋ฆญ ์ธํ„ฐํŽ˜์ด์Šค๋“ค์ด ๊ณผํ•˜๊ฒŒ ์ƒ์†๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•œ ๋ฌธ์ œ์ด๋‹ค

์ด์ฒ˜๋Ÿผ ์ฝ”๋“œ๋ฅผ ์ƒ์†๋ฐ›์•„ Stack๊ณผ Queue๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์€ ์ž˜๋ชป๋œ ์„ค๊ณ„์ด๋‹ค. Stack๊ณผ Queue์˜ ๋™์ž‘์€ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์ƒ์†๋ณด๋‹ค๋Š” ๊ฐ๊ฐ์˜ ๋™์ž‘์„ ๊ตฌํ˜„ํ•œ ๋ณ„๋„์˜ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.

๐Ÿ”‘ ์„œ๋ธŒํƒ€์ดํ•‘

๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜์›์น™์ด๋ž€ ๊ฐ„๋‹จํžˆ ๋งํ•ด "์ƒ์†์„ ํ•  ๋•Œ ์„œ๋ธŒํด๋ž˜์‹ฑ์€ ๋‚˜์˜๊ณ  ์„œ๋ธŒํƒ€์ดํ•‘์„ ํ•ด์•ผ ํ•œ๋‹ค"๋ผ๋Š” ์›์น™

์„œ๋ธŒํƒ€์ดํ•‘์— ๋Œ€ํ•ด ์กฐ์˜ํ˜ธ(2019)๋Š” ์˜ค๋ธŒ์ ํŠธ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค๋ช…ํ•œ๋‹ค.

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

์ฆ‰, ์„œ๋ธŒ ํด๋ž˜์‹ฑ ๊ด€์ ์œผ๋กœ ์ƒ์†ํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด๋‹ค๋Š” ์ ์„ ์„œ๋ธŒํƒ€์ดํ•‘์—์„œ๋Š” ๋งํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

๐ŸŒฑ ๋ฌธ์ œ์  2 : ์บก์Šํ™” ์œ„๋ฐ˜, ๋ฉ”์„œ๋“œ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ์˜ค์ž‘๋™

์ƒ์œ„ ํด๋ž˜์Šค๊ฐ€ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„๋˜๋Š๋ƒ์— ๋”ฐ๋ผ ํ•˜์œ„ ํด๋ž˜์Šค์˜ ๋™์ž‘์— ์ด์ƒ์ด ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค.

์—ฌ๊ธฐ์„œ ์บก์Šํ™”๋ž€, ๋‹จ์ˆœํžˆ private ๋ณ€์ˆ˜๋กœ Getter / Setter ๋ฅผ ์–˜๊ธฐํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค. ์บก์Šํ™”(์ •๋ณด ์€๋‹‰)์€ ๊ฐ์ฒด๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ๊ธฐ๋Šฅ์„ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š”์ง€๋ฅผ ๊ฐ์ถ”๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๋Š” ํด๋ž˜์Šค ์ž๋ฃŒํ˜•์„ ์ด์šฉํ• ๋•Œ ๋‚ด๋ถ€ ๋™์ž‘์„ ์•Œํ•„์š”์—†์ด ๋‹จ์ˆœํžˆ ๋ฉ”์†Œ๋“œ๋งŒ ๊ฐ–๋‹ค ์“ฐ๋ฉด ๋œ๋‹ค. ๋‹จ, ๋‚ด๋ถ€ ๋™์ž‘์„ ์•Œ ํ•„์š”๊ฐ€ ์—†๋‹ค๋Š” ๋ง์€ ์‹ ๋ขฐ์„ฑ์ด ๋ณด์žฅ๋˜์–ด์•ผ ํ•œ๋‹ค๋Š” ๋ง์ด๊ธฐ๋„ ํ•˜๋‹ค. ์บก์Šํ™”๊ฐ€ ๊นจ์ง„๊ฑด ์ด๋Ÿฌํ•œ ์‹ ๋ขฐ์„ฑ์ด ๊นจ์ง„๊ฒƒ์ด๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.

์ž˜๋ชป๋œ ์ƒ์†์˜ ์˜ˆ

public class InstrumentedHashSet<E> extends HashSet<E> {
    private int addCount = 0;

    public InstrumentedHashSet() { }

    @Override
    public boolean add(E e) {
        addCount++;
        return super.add(e);
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        addCount += c.size();
        return super.addAll(c);
    }

    public int getAddCount() {
        return addCount;
    }
}
InstrumentedHashSet<String> s = new InstrumentedHashSet<>();
s.addAll(Arrays.asList("ํ‹ฑ", "ํƒํƒ", "ํŽ‘"));

System.out.println(s.getAddCount()); // ์˜ˆ์ƒ: 3, ์‹ค์ œ: 6

์ผ๋ฐ˜์ ์œผ๋กœ ์œ„ ์ฝ”๋“œ ์‹คํ–‰ ํ›„ addCount๊ฐ€ 3์ด ๋  ๊ฒƒ์ด๋ผ ์˜ˆ์ƒํ•  ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” 6์ด๋‹ค. ์ด์œ ๋Š” ๋ถ€๋ชจ ํด๋ž˜์Šค์ธ HashSet์˜ addAll ๋ฉ”์„œ๋“œ ์•ˆ์—์„œ add๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

public boolean addAll(@NotNull Collection<? extends E> c) {
    boolean modified = false;
    for (E e : c) {
        if (add(e)) { // ๋‚ด๋ถ€์—์„œ ์ž์ฒด์ ์œผ๋กœ add()๋ฅผ ๊ณ„์† ํ˜ธ์ถœํ•œ๊ฑฐ์ž„
            modified = true;
        }
    }
    return modified;
}

addAll์„ ํ˜ธ์ถœํ•˜๋ฉด ๋‚ด๋ถ€์—์„œ add๋ฅผ ํ˜ธ์ถœํ•˜๋Š”๋ฐ add๊ฐ€ ์ƒ์œ„ ํด๋ž˜์Šค์˜ add๋ฅผ ํ˜ธ์ถœํ• ์ค„ ์•Œ์•˜์ง€๋งŒ InstrumentedHashSet์˜ add๋ฅผ ํ˜ธ์ถœํ–ˆ๋‹ค.

์œ„์—์„œ์˜ ๋ฌธ์ œ๋Š” ๋ฉ”์„œ๋“œ ์žฌ์ •์˜ ์‹œ ๋‹น์žฅ์€ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์œผ๋‚˜, HashSet์˜ addAll์ด add ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด ๊ตฌํ˜„ํ–ˆ์Œ์„ ๊ฐ€์ •ํ•œ ํ•ด๋ฒ•์ด๋ผ๋Š” ํ•œ๊ณ„๋ฅผ ์ง€๋‹Œ๋‹ค. ์ด์ฒ˜๋Ÿผ ์ž์‹ ์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์„ ์‚ฌ์šฉํ•˜๋Š” ์ž๊ธฐ์‚ฌ์šฉ(self-use) ์—ฌ๋ถ€๋Š” ํ•ด๋‹น ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„ ๋ฐฉ์‹ ์— ํ•ด๋‹นํ•˜๋ฉฐ, ์ž๋ฐ” ํ”Œ๋žซํผ ์ „๋ฐ˜์ ์ธ ์ •์ฑ…์ธ์ง€, ๊ทธ๋ž˜์„œ ๋‹ค์Œ ๋ฆด๋ฆฌ์Šค์—์„œ๋„ ์œ ์ง€๋ ์ง€๋Š” ์•Œ ์ˆ˜ ์—†๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋Ÿฐ ๊ฐ€์ •์— ๊ธฐ๋Œ„ InstrumentedHashSet๋„ ๊นจ์ง€๊ธฐ ์‰ฝ๋‹ค.

addAll ๋ฉ”์„œ๋“œ๋ฅผ ๋‹ค๋ฅธ ์‹์œผ๋กœ ์žฌ์ •์˜ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ์ฃผ์–ด์ง„ ์ปฌ๋ ‰์…˜์„ ์ˆœํšŒํ•˜๋ฉฐ ์›์†Œ ํ•˜๋‚˜๋‹น add ๋ฉ”์„œ๋“œ๋ฅผ ํ•˜๋‚˜๋งŒ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์กฐ๊ธˆ ๋‚˜์€ ๋ฐฉ๋ฒ•์ด์ง€๋งŒ ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ ๋™์ž‘์„ ๋‹ค์‹œ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์€ ์–ด๋ ต๊ณ , ๋น„์šฉ์ด ๋“ ๋‹ค. ๋˜ํ•œ ํ•˜์œ„ ํด๋ž˜์Šค์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” private ํ•„๋“œ๋ฅผ ์จ์•ผ ํ•œ๋‹ค๋ฉด ์ด ๋ฐฉ์‹์œผ๋กœ๋Š” ๊ตฌํ˜„ ์ž์ฒด๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

  • ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๊ตฌํ˜„์— ์˜์กด: HashSet์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„์ด addAll()์—์„œ add()๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์— ์˜์กดํ•˜๊ณ  ์žˆ๋‹ค.
  • ๋ฉ”์„œ๋“œ ์˜ค๋ฒ„๋ผ์ด๋”ฉ์˜ ์œ„ํ—˜์„ฑ: ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•˜๋ฉด, ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„์ด ๋ณ€๊ฒฝ๋  ๋•Œ ํ•˜์œ„ ํด๋ž˜์Šค์˜ ๋™์ž‘์ด ์˜ˆ๊ธฐ์น˜ ์•Š๊ฒŒ ๋ณ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์œ„์—์„œ์˜ ๋ฌธ์ œ๋Š” ๋‹ค ๋ฉ”์„œ๋“œ ์žฌ์ •์˜ ์‹œ๋‹ˆ๊นŒ ์ƒˆ๋กœ์šด ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค๋ฉด?

์ด ๋ฐฉ์‹์ด ํ›จ์”ฌ ์•ˆ์ „ํ•œ ๊ฒƒ์€ ๋งž์ง€๋งŒ, ์œ„ํ—˜์ด ์ „ํ˜€ ์—†๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ๋‹ค์Œ ๋ฆด๋ฆฌ์Šค์—์„œ ์ƒ์œ„ ํด๋ž˜์Šค์— ์ƒˆ ๋ฉ”์„œ๋“œ๊ฐ€ ์ถ”๊ฐ€๋๋Š”๋ฐ, ํ•˜ํ•„ ํ•˜์œ„ ํด๋ž˜์Šค์— ์ถ”๊ฐ€ํ•œ ๋ฉ”์„œ๋“œ์™€ ์‹œ๊ทธ๋‹ˆ์ฒ˜๊ฐ€ ๊ฐ™๊ณ  ๋ฐ˜ํ™˜ ํƒ€์ž…์€ ๋‹ค๋ฅด๋‹ค๋ฉด ์—ฌ๋Ÿฌ๋ถ„์˜ ํด๋ž˜์Šค๋Š” ์ปดํŒŒ์ผ์กฐ์ฐจ ๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค.

๐ŸŒฑ ๋ฌธ์ œ์  3 : ๊ฐ•ํ•œ ๊ฒฐํ•ฉ๋„

์ƒ์†์€ ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๊ฐ•๋ ฅํ•œ ์ˆ˜๋‹จ์ด์ง€๋งŒ, ํ•ญ์ƒ ์ตœ์„ ์€ ์•„๋‹ˆ๋‹ค

๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€ ๋ณ€๊ฒฝ์ด ์ž์‹ ํด๋ž˜์Šค์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ์–ด ์œ ์—ฐ์„ฑ์ด ์ €ํ•˜๋œ๋‹ค. ์ƒ์†์„ ํ•˜๊ฒŒ ๋˜๋ฉด ๋ถ€๋ชจ ํด๋ž˜์Šค์™€ ์ž์‹ ํด๋ž˜์Šค์˜ ๊ด€๊ณ„๊ฐ€ ์ปดํŒŒ์ผ ์‹œ์ ์— ๊ด€๊ณ„๊ฐ€ ๊ฒฐ์ •๋˜์–ด ๊ฒฐํ•ฉ๋„๊ฐ€ ๋‹น์—ฐํžˆ ๋†’์•„์งˆ์ˆ˜ ๋ฐ–์— ์—†๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ํด๋ž˜์Šค B๊ฐ€ ํด๋ž˜์Šค A๋ฅผ ์ƒ์†(extends) ํ•œ๋‹ค๊ณ  ํ•˜๋ฉด, ์ฝ”๋“œ ์‹คํ–‰(๋Ÿฐํƒ€์ž„) ์ค‘๊ฐ„์— ํด๋ž˜์Šค C๋ฅผ ์ƒ์†ํ•˜๋„๋ก ๋ฐ”๊ฟ€์ˆ˜ ์—†๋‹ค. ์ฒ˜์Œ ์‹คํ–‰๋˜๊ธฐ ์ „์— ๋ฏธ๋ฆฌ ๊ทธ๋ ‡๊ฒŒ ๊ฒฐ์ •๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

  • ์บก์Šํ™” ์œ„๋ฐ˜ : ์ž์‹ ํด๋ž˜์Šค๊ฐ€ ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ๊ตฌํ˜„ ์„ธ๋ถ€ ์‚ฌํ•ญ์— ์˜์กดํ•˜๊ฒŒ๋˜๋ฉด, ์บก์Šํ™”๊ฐ€ ์•ฝํ™”๋œ๋‹ค.
  • ์žฌ์‚ฌ์šฉ์„ฑ ์ €ํ•˜ : ํŠน์ • ๊ตฌํ˜„์— ๊ฐ•ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋œ ์ƒ์† ๊ตฌ์กฐ๋Š” ์ƒˆ๋กœ์šด ์ƒํ™ฉ์— ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์–ด๋ ต๋‹ค.

๐ŸŒฑ ๋ฌธ์ œ์  4 : ์ž์‹์€ ๋ถ€๋ชจ์˜ ๊ฑฐ์šธ, ์•ˆ ์ข‹์€ ์ ๊นŒ์ง€? ๊ทธ๋ฆฌ๊ณ  ๋™์‹œ ์ˆ˜์ •

๋งˆ์น˜ ์ž์‹์€ ๋ถ€๋ชจ์˜ ๊ฑฐ์šธ์ด๋ผ๋Š” ๋ง์ฒ˜๋Ÿผ ๋ถ€๋ชจ์˜ ์•ˆ ์ข‹์€ ์ ์„ ์ž์‹ํด๋ž˜์Šค๋“ค์ด ๋‹ค ๋‹ฎ๊ฒŒ ๋œ๋‹ค.

[๊ฒฐํ•จ ์ƒ์†]
๋ถ€๋ชจ ํด๋ž˜์Šค์— ๊ฒฐํ•จ์ด ์žˆ์„ ๋•Œ ์ž์‹ ํด๋ž˜์Šค๋„ ๊ทธ ๊ฒฐํ•จ์„ ๊ทธ๋Œ€๋กœ ์ƒ์†๋ฐ›๊ฒŒ ๋˜๋Š” ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค.

class Vehicle {
    private int speed;

    public Vehicle(int speed) {
        this.speed = speed;
    }

    // ๊ฒฐํ•จ์ด ์žˆ๋Š” ๋ฉ”์„œ๋“œ: ์†๋„๊ฐ€ ์Œ์ˆ˜์ผ ๋•Œ๋„ ํ—ˆ์šฉ
    public void accelerate(int increment) {
        speed += increment;
    }

    public int getSpeed() {
        return speed;
    }
}

class Car extends Vehicle {
    public Car(int speed) {
        super(speed);
    }

    // Car๋Š” ๋ณ„๋„์˜ ๊ฒฐํ•จ์ด ์—†์œผ๋‚˜ ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ accelerate ๋ฉ”์„œ๋“œ ๊ฒฐํ•จ์„ ๊ทธ๋Œ€๋กœ ์ƒ์†
}

public class Main {
    public static void main(String[] args) {
        Car car = new Car(50);
        car.accelerate(-100);  // ์†๋„๊ฐ€ ์Œ์ˆ˜๊ฐ€ ๋  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ ๋ฐœ์ƒ
        System.out.println("Car speed: " + car.getSpeed());  // ์ถœ๋ ฅ ๊ฒฐ๊ณผ๊ฐ€ ์Œ์ˆ˜
    }
}

์œ„ ์ฝ”๋“œ์—์„œ Vehicle ํด๋ž˜์Šค์˜ accelerate ๋ฉ”์„œ๋“œ์— ๊ฒฐํ•จ์ด ์žˆ์–ด ์Œ์ˆ˜ ์†๋„๊ฐ€ ํ—ˆ์šฉ๋˜์ง€๋งŒ, ์ด ๊ฒฐํ•จ์ด ์ž์‹ ํด๋ž˜์Šค Car์—๋„ ๊ทธ๋Œ€๋กœ ์˜ํ–ฅ์„ ๋ฏธ์นœ๋‹ค.

[๋ถ€๋ชจ ํด๋ž˜์Šค์™€ ์ž์‹ ํด๋ž˜์Šค์˜ ๋™์‹œ ์ˆ˜์ • ๋ฌธ์ œ]
๋ถ€๋ชจ ํด๋ž˜์Šค๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ ์ž์‹ ํด๋ž˜์Šค์™€ ํ˜ธ์ถœ๋ถ€๋„ ๋ชจ๋‘ ์ˆ˜์ •ํ•ด์•ผ ํ•ด์•ผ ํ•จ

๐ŸŒฑ ๋ฌธ์ œ์  6 : ํด๋ž˜์Šค ํญ๋ฐœ(class explosion)

์ƒ์†์„ ๋‚จ์šฉํ•  ๊ฒฝ์šฐ ํด๋ž˜์Šค ํญ๋ฐœ(class explosion) ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฆ‰, ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด ์ƒ์†์„ ๊ณ„์†ํ•˜๋‹ค ๋ณด๋ฉด ํด๋ž˜์Šค๊ฐ€ ๊ธ‰๊ฒฉํžˆ ๋Š˜์–ด๋‚˜๊ณ , ์„œ๋กœ ๋ณต์žกํ•˜๊ฒŒ ์–ฝํžˆ๊ฒŒ ๋˜์–ด ๊ด€๋ฆฌ๊ฐ€ ์–ด๋ ค์›Œ์ง„๋‹ค. ์ด๋ฅผ ์กฐํ•ฉ์˜ ํญ๋ฐœ(combinational explosion)์ด๋ผ๊ณ ๋„ ๋ถ€๋ฅธ๋‹ค.

์ƒ์†์€ ์ปดํŒŒ์ผ ํƒ€์ž„์— ๊ฒฐ์ •๋˜๋ฏ€๋กœ, ์‹คํ–‰ ์ค‘์— ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค. ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์•„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.
์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ƒ์† ๋Œ€์‹  ํ•ฉ์„ฑ(Composition)์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ํ•ฉ์„ฑ์€ ๊ธฐ์กด ๊ฐ์ฒด๋ฅผ ํฌํ•จํ•˜๊ณ , ๊ทธ ๊ฐ์ฒด์— ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ƒ์†์˜ ๋ฌธ์ œ๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐ŸŒฑ ๋ฌธ์ œ์  7 : ๋‹จ์ผ ์ƒ์†์˜ ํ•œ๊ณ„

์ž๋ฐ”๋Š” ๋‹ค์ค‘ ์ƒ์†์„ ์ง€์›ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ํ•˜๋‚˜์˜ ํด๋ž˜์Šค๋Š” ์˜ค์ง ํ•˜๋‚˜์˜ ๋ถ€๋ชจ ํด๋ž˜์Šค๋งŒ ์ƒ์†๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

๋‹ค์ค‘ ์ƒ์†์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒ์† ๊ณ„์ธต์„ ๋ณต์žกํ•˜๊ฒŒ ๋‚˜๋ˆ ์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

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

2. ์ƒ์†์˜ ๋Œ€์•ˆ ์ปดํฌ์ง€์…˜(composition)

ํ•˜๋‚˜์˜ ํด๋ž˜์Šค๊ฐ€ ๋‹ค๋ฅธ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ํฌํ•จํ•˜์—ฌ, ๊ทธ ์ธ์Šคํ„ด์Šค์˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ์‹

1) ํ•ฉ์„ฑ์ด๋ž€?

ํ•ฉ์„ฑ์€ ๊ฐ์ฒด ๊ฐ„์˜ ๊ด€๊ณ„๊ฐ€ ์ˆ˜์ง๊ด€๊ณ„๊ฐ€ ์•„๋‹Œ ์ˆ˜ํ‰ ๊ด€๊ณ„๊ฐ€ ๋œ๋‹ค.

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

2) ํ•ฉ์„ฑ ์˜ˆ์‹œ

์ปดํ“จํ„ฐ(Computer)์™€ ๋ชจ๋‹ˆํ„ฐ(Monitor)์˜ ๊ด€๊ณ„๋ฅผ ์˜ˆ๋กœ ๋“ค์–ด๋ณด๊ฒ ๋‹ค. ์ปดํ“จํ„ฐ๋Š” ๋ชจ๋‹ˆํ„ฐ๊ฐ€ ํ•„์š”ํ•˜์ง€๋งŒ, ๋ชจ๋‹ˆํ„ฐ๋ฅผ ์ƒ์†๋ฐ›์„ ํ•„์š”๋Š” ์—†๋‹ค. ๋Œ€์‹  ๋ชจ๋‹ˆํ„ฐ๋ฅผ ํ•ฉ์„ฑํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ ํ•ฉํ•˜๋‹ค.

// Computer ํด๋ž˜์Šค
class Computer {
    Monitor monitor; // ํ•„๋“œ๋กœ Monitor ํด๋ž˜์Šค ๋ณ€์ˆ˜๋ฅผ ๊ฐ–๋Š”๋‹ค (Has-A ๊ด€๊ณ„)

    Computer(Monitor monitor) {
        this.monitor = monitor; // ์ƒ์„ฑ์ž ์ดˆ๊ธฐํ™” ์‹œ Monitor ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ›์Œ
    }

    void display() {
        System.out.printf("%s ๋ชจ๋‹ˆํ„ฐ๋กœ ํ™”๋ฉด ์ถœ๋ ฅ ์ค‘...\n", monitor.getMonitorType());
    }

    void turnOff() {
        System.out.printf("%s ๋ชจ๋‹ˆํ„ฐ๋ฅผ ๋•๋‹ˆ๋‹ค...\n", monitor.getMonitorType());
    }
}

// Monitor ํด๋ž˜์Šค
class Monitor {
    String monitorType; // ๋ชจ๋‹ˆํ„ฐ ์ข…๋ฅ˜ (์˜ˆ: LCD, LED)

    Monitor(String type) {
        this.monitorType = type;
    }

    String getMonitorType() {
        return this.monitorType;
    }
}

// Main ํด๋ž˜์Šค
public class Main {
    public static void main(String[] args) {
        // LCD ๋ชจ๋‹ˆํ„ฐ๊ฐ€ ์—ฐ๊ฒฐ๋œ ์ปดํ“จํ„ฐ
        Computer lcdComputer = new Computer(new Monitor("LCD"));
        lcdComputer.display(); // LCD ๋ชจ๋‹ˆํ„ฐ๋กœ ํ™”๋ฉด ์ถœ๋ ฅ ์ค‘...

        // LED ๋ชจ๋‹ˆํ„ฐ๊ฐ€ ์—ฐ๊ฒฐ๋œ ์ปดํ“จํ„ฐ
        Computer ledComputer = new Computer(new Monitor("LED"));
        ledComputer.display(); // LED ๋ชจ๋‹ˆํ„ฐ๋กœ ํ™”๋ฉด ์ถœ๋ ฅ ์ค‘...
        
        lcdComputer.turnOff(); // LCD ๋ชจ๋‹ˆํ„ฐ๋ฅผ ๋•๋‹ˆ๋‹ค...
        ledComputer.turnOff(); // LED ๋ชจ๋‹ˆํ„ฐ๋ฅผ ๋•๋‹ˆ๋‹ค...
    }
}
  • Computer ํด๋ž˜์Šค๋Š” Monitor ํด๋ž˜์Šค๋ฅผ ํ•„๋“œ๋กœ ๊ฐ€์ง„๋‹ค. ์ด๊ฒƒ์ด ๋ฐ”๋กœ ํ•ฉ์„ฑ์˜ ์˜ˆ๋กœ ์ปดํ“จํ„ฐ๋Š” ๋ชจ๋‹ˆํ„ฐ๋ฅผ ํ•„์š”๋กœ ํ•˜์ง€๋งŒ, ๋ชจ๋‹ˆํ„ฐ๋ฅผ ์ƒ์†ํ•˜์ง€ ์•Š๊ณ  ์ธ์Šคํ„ด์Šค๋กœ ์ฐธ์กฐํ•˜์—ฌ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•œ๋‹ค.
  • Computer ํด๋ž˜์Šค์˜ ์ƒ์„ฑ์ž๋Š” Monitor ๊ฐ์ฒด๋ฅผ ๋ฐ›์•„์„œ, ๊ทธ ๊ฐ์ฒด์˜ monitorType์„ ํ†ตํ•ด ๋ชจ๋‹ˆํ„ฐ ์ข…๋ฅ˜์— ๋”ฐ๋ฅธ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  • Monitor ํด๋ž˜์Šค๋Š” ๋ชจ๋‹ˆํ„ฐ์˜ ์ข…๋ฅ˜(monitorType)๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ํ•„๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ, ์ด๋ฅผ Computer ํด๋ž˜์Šค๊ฐ€ ํ˜ธ์ถœํ•˜์—ฌ ์‚ฌ์šฉํ•œ๋‹ค.

์œ„์˜ ์ดˆ๊ธฐํ™” ์ฝ”๋“œ์—์„œ ๋ณผ์ˆ˜ ์žˆ๋“ฏ์ด, ๊ธฐ์กด ํด๋ž˜์Šค๋ฅผ ํ™•์žฅํ•˜๋Š” ๋Œ€์‹ , ์ƒˆ๋กœ์šด ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  private ํ•„๋“œ๋กœ ๊ธฐ์กด ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐธ์กฐํ•˜๊ฒŒ ํ•œ ๊ฒƒ์ด๋‹ค.

์ƒ์†์˜ ๋ฌธ์ œ์˜ ๋Œ€์•ˆ๋ฒ•์ธ ํ•ฉ์„ฑ์€ ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ํ•ด์„œ ๋ฌด์กฐ๊ฑด ์ƒ์†ํ•˜์ง€๋ง๊ณ , ๋”ฐ๋กœ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜์— ์ €์žฅํ•˜์—ฌ ๊ฐ€์ ธ๋‹ค ์“ด๋‹ค๋Š” ์›๋ฆฌ์ด๋‹ค.

์ƒˆ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ๋“ค์€ (private ํ•„๋“œ๋กœ ์ฐธ์กฐํ•˜๋Š”) ๊ธฐ์กด ํด๋ž˜์Šค์˜ ๋Œ€์‘ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœ ํ•ด ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ด ๋ฐฉ์‹์„ ์ „๋‹ฌ(forwarding)์ด๋ผ ํ•˜๋ฉฐ, ์ƒˆ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๋“ค์„ ์ „๋‹ฌ ๋ฉ”์„œ๋“œ(forwarding method)๋ผ ๋ถ€๋ฅธ๋‹ค.

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

3) ์ปดํฌ์ง€์…˜ ์‚ฌ์šฉํ•˜๊ธฐ

์ƒ์† ๋Œ€์‹  ์ปดํฌ์ง€์…˜(Composition)์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ์กด Set ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ์‹ธ๋Š” ๋ž˜ํผ ํด๋ž˜์Šค(Wrapper Class)๋ฅผ ๋งŒ๋“ค์–ด๊ฐ€์ž.

public class InstrumentedSet<E> implements Set<E> {
    private final Set<E> set;
    private int addCount = 0;

    public InstrumentedSet(Set<E> set) {
        this.set = set;
    }

    @Override
    public boolean add(E e) {
        addCount++;
        return set.add(e);
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        addCount += c.size();
        return set.addAll(c);
    }

    public int getAddCount() {
        return addCount;
    }

    // ๋‚˜๋จธ์ง€ Set ์ธํ„ฐํŽ˜์ด์Šค ๋ฉ”์„œ๋“œ๋“ค์€ set ์ธ์Šคํ„ด์Šค์— ์œ„์ž„
    @Override
    public int size() {
        return set.size();
    }

    @Override
    public boolean isEmpty() {
        return set.isEmpty();
    }

    // ... ๊ธฐํƒ€ ๋ฉ”์„œ๋“œ๋“ค๋„ ๋™์ผํ•˜๊ฒŒ ์œ„์ž„
}

์„ค๋ช…:

  • InstrumentedSet์€ Set ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ , ๋‚ด๋ถ€์— ์‹ค์ œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  Set ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ง„๋‹ค.
  • ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋Š” ๋‚ด๋ถ€ set ๊ฐ์ฒด์— ์ž‘์—…์„ ์œ„์ž„ํ•œ๋‹ค.
  • add()์™€ addAll() ๋ฉ”์„œ๋“œ์—์„œ addCount๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ์ฆ๊ฐ€์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.
  • ์ƒ์†์ด ์•„๋‹Œ ์ปดํฌ์ง€์…˜์„ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„์— ์˜์กดํ•˜์ง€ ์•Š๋Š”๋‹ค.

์‚ฌ์šฉ ์˜ˆ์‹œ:

Set<String> s = new InstrumentedSet<>(new HashSet<>());
s.addAll(Arrays.asList("ํ‹ฑ", "ํƒํƒ", "ํŽ‘"));

System.out.println(((InstrumentedSet<String>) s).getAddCount()); // ์ถœ๋ ฅ: 3
  • ์•ˆ์ „์„ฑ: ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„ ๋ณ€ํ™”์— ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๋Š”๋‹ค.
  • ์œ ์—ฐ์„ฑ: ๊ธฐ์กด ํด๋ž˜์Šค์˜ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•  ๋•Œ ๋” ์•ˆ์ „ํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์žฌ์‚ฌ์šฉ์„ฑ: ๋‹ค์–‘ํ•œ ํด๋ž˜์Šค์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•˜๊ธฐ ์‰ฝ๋‹ค.

์œ„์ž„ ๋ฉ”์„œ๋“œ๋ฅผ ์ผ์ผ์ด ์ž‘์„ฑํ•˜๋Š” ๋Œ€์‹ , ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํฌ์›Œ๋”ฉ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์„œ ์ค‘๋ณต ์ฝ”๋“œ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

public class ForwardingSet<E> implements Set<E> {
    protected final Set<E> s;

    public ForwardingSet(Set<E> s) {
        this.s = s;
    }

    @Override
    public boolean add(E e) { return s.add(e); }

    @Override
    public boolean addAll(Collection<? extends E> c) { return s.addAll(c); }

    // ๋‚˜๋จธ์ง€ ๋ฉ”์„œ๋“œ๋“ค๋„ ๋™์ผํ•˜๊ฒŒ s์— ์œ„์ž„
    @Override
    public int size() { return s.size(); }

    @Override
    public boolean isEmpty() { return s.isEmpty(); }

    // ... ๊ธฐํƒ€ ๋ฉ”์„œ๋“œ๋“ค๋„ ๋™์ผํ•˜๊ฒŒ ์œ„์ž„
}

์ด์ œ InstrumentedSet์€ ForwardingSet์„ ์ƒ์†๋ฐ›์•„ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด ๋จ

public class InstrumentedSet<E> extends ForwardingSet<E> {
    private int addCount = 0;

    public InstrumentedSet(Set<E> s) {
        super(s);
    }

    @Override
    public boolean add(E e) {
        addCount++;
        return super.add(e);
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        addCount += c.size();
        return super.addAll(c);
    }

    public int getAddCount() {
        return addCount;
    }
}

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

Set<Instant> times = new InstrumentedSet<>(new TreeSet<>(cmp));
Set<E> s = new InstrumentedSet<>(new HashSet<>(INIT_CAPACITY));

๋‹ค๋ฅธ Set ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ์‹ธ๊ณ  ์žˆ๋‹ค๋Š” ๋œป์—์„œ InstrumentedSet ๊ฐ™์€ ํด๋ž˜์Šค๋ฅผ ๋ž˜ํผ ํด๋ž˜์Šค๋ผ ํ•˜๋ฉฐ, ๋‹ค๋ฅธ Set์— ๊ณ„์ธก ๊ธฐ๋Šฅ์„ ๋ง์”Œ์šด๋‹ค๋Š” ๋œป์—์„œ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ํŒจํ„ด์ด๋ผ๊ณ  ํ•œ๋‹ค. ์ปดํฌ์ง€์…˜๊ณผ ์ „๋‹ฌ์˜ ์กฐํ•ฉ์€ ๋„“์€ ์˜๋ฏธ๋กœ ์œ„์ž„(delegation)์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

์ƒ์†์€ ๋ฐ˜๋“œ์‹œ ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ์ƒ์œ„ ํด๋ž˜์Šค์˜ '์ง„์งœ' ํ•˜์œ„ ํƒ€์ž…์ธ ์ƒํ™ฉ์—์„œ๋งŒ ์“ฐ์—ฌ์•ผ ํ•œ๋‹ค. ๋‹ค๋ฅด๊ฒŒ ๋งํ•˜๋ฉด, ํด๋ž˜์Šค B๊ฐ€ ํด๋ž˜์Šค A์™€ is-a ๊ด€๊ณ„์ผ ๋•Œ๋งŒ ํด๋ž˜์Šค A๋ฅผ ์ƒ์†ํ•ด์•ผ ํ•œ๋‹ค.

์ปดํฌ์ง€์…˜์„ ์จ์•ผ ํ•  ์ƒํ™ฉ์—์„œ ์ƒ์†์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฑด ๋‚ด๋ถ€ ๊ตฌํ˜„์„ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋…ธ์ถœํ•˜๋Š” ๊ผด์ด๋‹ค. ๊ทธ ๊ฒฐ๊ณผ API๊ฐ€ ๋‚ด๋ถ€ ๊ตฌํ˜„์— ๋ฌถ์ด๊ณ  ๊ทธ ํด๋ž˜์Šค์˜ ์„ฑ๋Šฅ๋„ ์˜์›ํžˆ ์ œํ•œ๋œ๋‹ค. ๋” ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋…ธ์ถœ๋œ ๋‚ด๋ถ€์— ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค.

๋ž˜ํผ ํด๋ž˜์Šค๋Š” ๋‹จ์ ์ด ๊ฑฐ์˜ ์—†๋‹ค. ํ•œ ๊ฐ€์ง€, ๋ž˜ํผ ํด๋ž˜์Šค๊ฐ€ ์ฝœ๋ฐฑ(callback) ํ”„๋ ˆ์ž„์›Œํฌ์™€๋Š” ์–ด์šธ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ๋งŒ ์ฃผ์˜ํ•˜๋ฉด ๋œ๋‹ค.

์ฝœ๋ฐฑ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ๋Š” ์ž๊ธฐ ์ž์‹ ์˜ ์ฐธ์กฐ๋ฅผ ๋‹ค๋ฅธ ๊ฐ์ฒด์— ๋„˜๊ฒจ์„œ ๋‹ค์Œ ํ˜ธ์ถœ(์ฝœ๋ฐฑ) ๋•Œ ์‚ฌ์šฉํ•˜๋„๋ก ํ•œ๋‹ค. ๋‚ด๋ถ€ ๊ฐ์ฒด๋Š” ์ž์‹ ์„ ๊ฐ์‹ธ๊ณ  ์žˆ๋Š” ๋ž˜ํผ์˜ ์กด์žฌ๋ฅผ ๋ชจ๋ฅด๋‹ˆ ๋Œ€์‹  ์ž์‹ (this)์˜ ์ฐธ์กฐ๋ฅผ ๋„˜๊ธฐ๊ณ , ์ฝœ๋ฐฑ ๋•Œ๋Š” ๋ž˜ํผ๊ฐ€ ์•„๋‹Œ ๋‚ด๋ถ€ ๊ฐ์ฒด๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋œ๋‹ค. ์ด๋ฅผ SELF ๋ฌธ์ œ๋ผ๊ณ  ํ•œ๋‹ค.

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

4) ์ปดํฌ์ง€์…˜์˜ ์žฅ์ 

ํ•ฉ์„ฑ(Composition)์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” ์œ ์—ฐ์„ฑ๊ณผ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•ด์„œ์ž…๋‹ˆ๋‹ค. ์ƒ์†์— ๋น„ํ•ด ํ•ฉ์„ฑ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด์ ์ด ์žˆ๋‹ค.

  1. ์œ ์—ฐํ•œ ๊ฐ์ฒด ๊ด€๊ณ„ ๊ด€๋ฆฌ

    ์ƒ์†์—์„œ๋Š” ๊ฐ์ฒด ๊ฐ„์˜ ๊ด€๊ณ„๊ฐ€ ๊ณ ์ •๋˜์ง€๋งŒ, ํ•ฉ์„ฑ์—์„œ๋Š” ๋” ์œ ์—ฐํ•˜๊ฒŒ ๊ฐ์ฒด๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

โŒ ์ƒ์† ์˜ˆ์‹œ (์ƒ์†์œผ๋กœ ๊ณ ์ •๋œ ๊ด€๊ณ„)

// ๋ถ€๋ชจ ํด๋ž˜์Šค: Animal
class Animal {
    public void eat() {
        System.out.println("This animal is eating.");
    }
}

// ์ž์‹ ํด๋ž˜์Šค: Dog
class Dog extends Animal {
    public void bark() {
        System.out.println("The dog is barking.");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.eat();  // ์ƒ์†๋œ ๋ฉ”์„œ๋“œ: Dog๊ฐ€ Animal์˜ eat ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉ
        dog.bark(); // Dog ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ
    }
}

์œ„ ์ฝ”๋“œ๋Š” Dog ํด๋ž˜์Šค๊ฐ€ Animal ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•˜๋ฏ€๋กœ, Dog ๊ฐ์ฒด๋Š” Animal์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์†๋ฐ›๋Š”๋‹ค. ํ•˜์ง€๋งŒ ๊ด€๊ณ„๊ฐ€ ๊ณ ์ •๋˜์–ด ๋ณ€๊ฒฝํ•˜๊ธฐ ์–ด๋ ต๋‹ค.

โญ•ํ•ฉ์„ฑ ์˜ˆ์‹œ (์œ ์—ฐํ•œ ๊ด€๊ณ„)

// ๋…๋ฆฝ์ ์ธ ๊ธฐ๋Šฅ ํด๋ž˜์Šค: SoundMaker
class SoundMaker {
    public void makeSound(String sound) {
        System.out.println(sound);
    }
}

// ํ•ฉ์„ฑ์„ ์ด์šฉํ•œ Dog ํด๋ž˜์Šค
class Dog {
    private SoundMaker soundMaker;  // Dog ํด๋ž˜์Šค๋Š” SoundMaker๋ฅผ ์‚ฌ์šฉ (has-a ๊ด€๊ณ„)

    public Dog() {
        this.soundMaker = new SoundMaker();
    }

    public void bark() {
        soundMaker.makeSound("The dog is barking.");
    }

    public void eat() {
        System.out.println("The dog is eating.");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.bark();  // ํ•ฉ์„ฑ์„ ์ด์šฉํ•˜์—ฌ ์†Œ๋ฆฌ๋ฅผ ๋งŒ๋“ฆ
        dog.eat();   // ๋…๋ฆฝ์ ์ธ Dog์˜ ๋ฉ”์„œ๋“œ
    }
}

์—ฌ๊ธฐ์„œ๋Š” Dog ํด๋ž˜์Šค๊ฐ€ SoundMaker ๊ฐ์ฒด๋ฅผ ์กฐ๋ฆฝ(ํ•ฉ์„ฑ)ํ•˜์—ฌ ๋” ์œ ์—ฐํ•˜๊ฒŒ ๋™์ž‘์„ ์ •์˜

  1. ๋‹ค์ค‘ ์ƒ์† ๋ฌธ์ œ ํ•ด๊ฒฐ

    ์ž๋ฐ”๋Š” ๋‹ค์ค‘ ์ƒ์†์„ ์ง€์›ํ•˜์ง€ ์•Š์ง€๋งŒ, ํ•ฉ์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ ๊ฐ์ฒด๋ฅผ ํ•ฉ์„ฑํ•˜์—ฌ ๋‹ค์ค‘ ์ƒ์†๊ณผ ์œ ์‚ฌํ•œ ํšจ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

โญ• ํ•ฉ์„ฑ ์˜ˆ์‹œ (๋‹ค์ค‘ ์ƒ์† ๋Œ€์ฒด)

// ๋…๋ฆฝ์ ์ธ ๊ธฐ๋Šฅ ํด๋ž˜์Šค: Engine
class Engine {
    public void start() {
        System.out.println("Engine is starting...");
    }
}

// ๋…๋ฆฝ์ ์ธ ๊ธฐ๋Šฅ ํด๋ž˜์Šค: GPS
class GPS {
    public void activate() {
        System.out.println("GPS is activated.");
    }
}

// Car ํด๋ž˜์Šค๊ฐ€ Engine๊ณผ GPS๋ฅผ ํ•ฉ์„ฑ
class Car {
    private Engine engine; // Car๋Š” Engine์„ ๊ฐ€์ง (has-a)
    private GPS gps;       // Car๋Š” GPS๋ฅผ ๊ฐ€์ง (has-a)

    public Car() {
        this.engine = new Engine();
        this.gps = new GPS();
    }

    public void drive() {
        engine.start();
        gps.activate();
        System.out.println("Car is driving.");
    }
}

public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        car.drive();  // Car๋Š” Engine๊ณผ GPS ๊ธฐ๋Šฅ์„ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ
    }
}

์œ„ ์ฝ”๋“œ์—์„œ๋Š” Car๊ฐ€ Engine๊ณผ GPS ๋‘ ๊ฐ์ฒด๋ฅผ ํ•ฉ์„ฑํ•˜์—ฌ ๋‹ค์ค‘ ์ƒ์† ์—†์ด ๋‘ ๊ฐ์ฒด์˜ ๊ธฐ๋Šฅ์„ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์ƒ์†์˜ ๋ฌธ์ œ ํ•ด๊ฒฐ

    ์ƒ์†์€ ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ์„ธ๋ถ€ ๊ตฌํ˜„์— ์˜์กดํ•˜์ง€๋งŒ, ํ•ฉ์„ฑ์€ ๊ฐ์ฒด์˜ ํ–‰๋™์„ ์œ„์ž„ํ•จ์œผ๋กœ์จ ๋” ๋…๋ฆฝ์ ์ธ ๊ด€๊ณ„๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

โŒ์ƒ์†์˜ ๋ฌธ์ œ ์˜ˆ์‹œ

// ๋ถ€๋ชจ ํด๋ž˜์Šค: Beverage (์Œ๋ฃŒ)
class Beverage {
    public void drink() {
        System.out.println("Drinking a beverage.");
    }
}

// ์ž์‹ ํด๋ž˜์Šค: Juice
class Juice extends Beverage {
    public void addIce() {
        System.out.println("Adding ice to the juice.");
    }
}

public class Main {
    public static void main(String[] args) {
        Juice juice = new Juice();
        juice.drink();  // ์ƒ์†๋œ ๋ฉ”์„œ๋“œ: Juice๊ฐ€ Beverage์˜ drink ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉ
        juice.addIce();
    }
}

์ด ์ฝ”๋“œ์—์„œ ๋งŒ์•ฝ Beverage ํด๋ž˜์Šค์— ๋ณ€๊ฒฝ์ด ์ƒ๊ธฐ๋ฉด Juice ํด๋ž˜์Šค์—๋„ ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ถ€๋ชจ ํด๋ž˜์Šค์— ์˜์กดํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ๋‹ค.

โญ• ํ•ฉ์„ฑ์œผ๋กœ ํ•ด๊ฒฐ

// ๋…๋ฆฝ์ ์ธ ๊ธฐ๋Šฅ ํด๋ž˜์Šค: IceMaker
class IceMaker {
    public void addIce() {
        System.out.println("Ice is added.");
    }
}

// Juice ํด๋ž˜์Šค๊ฐ€ IceMaker๋ฅผ ํ•ฉ์„ฑํ•˜์—ฌ ์‚ฌ์šฉ
class Juice {
    private IceMaker iceMaker;  // Juice๋Š” IceMaker๋ฅผ ํ•ฉ์„ฑ (has-a)

    public Juice() {
        this.iceMaker = new IceMaker();
    }

    public void drink() {
        System.out.println("Drinking juice.");
    }

    public void addIce() {
        iceMaker.addIce();  // IceMaker ๊ฐ์ฒด์— ๊ธฐ๋Šฅ์„ ์œ„์ž„
    }
}

public class Main {
    public static void main(String[] args) {
        Juice juice = new Juice();
        juice.drink();
        juice.addIce();  // Juice๋Š” IceMaker ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•จ
    }
}

์ด ๋ฐฉ์‹์€ Juice๊ฐ€ IceMaker์˜ ๋‚ด๋ถ€ ๋™์ž‘์— ์˜์กดํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋” ๋…๋ฆฝ์ ์ด๊ณ  ์œ ์—ฐํ•˜๊ฒŒ ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ๋‹ค.

  1. ์บก์Šํ™” ๋ณด์žฅ

    ์ƒ์†์€ ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ๋ชจ๋“  public ๋ฉ”์„œ๋“œ๋ฅผ ์ž์‹ ํด๋ž˜์Šค์— ๊ณต๊ฐœํ•˜๋Š” ๋ฐ˜๋ฉด, ํ•ฉ์„ฑ์€ ํ•„์š”ํ•œ ๋ฉ”์„œ๋“œ๋งŒ ๋…ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.

โŒ ์ƒ์†์—์„œ์˜ ๋ฌธ์ œ

class Vector {
    public void addElement(String element) {
        System.out.println("Element added to vector: " + element);
    }
}

class Stack extends Vector {
    public void push(String element) {
        addElement(element);
    }

    public void pop() {
        System.out.println("Element removed from stack.");
    }
}

public class Main {
    public static void main(String[] args) {
        Stack stack = new Stack();
        stack.push("item");
        stack.addElement("another item");  // ๋ถˆํ•„์š”ํ•œ ๋ถ€๋ชจ ํด๋ž˜์Šค ๋ฉ”์„œ๋“œ๊ฐ€ ๋…ธ์ถœ๋จ
        stack.pop();
    }
}

์ด ์ฝ”๋“œ์—์„œ๋Š” Stack ํด๋ž˜์Šค์—์„œ ๋ถˆํ•„์š”ํ•œ addElement ๋ฉ”์„œ๋“œ๊ฐ€ ๋…ธ์ถœ๋˜์–ด ์ž˜๋ชป๋œ ์‚ฌ์šฉ์„ ํ—ˆ์šฉํ•˜๊ฒŒ ๋œ๋‹ค.

โญ• ํ•ฉ์„ฑ์œผ๋กœ ์บก์Šํ™”

// Vector์™€ ๋™์ผํ•œ ๊ธฐ๋Šฅ์„ ๊ฐ€์ง„ ํด๋ž˜์Šค: ListManager
class ListManager {
    public void addElement(String element) {
        System.out.println("Element added to list: " + element);
    }
}

// Stack์€ ListManager๋ฅผ ํ•ฉ์„ฑํ•˜์—ฌ ํ•„์š”ํ•œ ๋ฉ”์„œ๋“œ๋งŒ ๋…ธ์ถœ
class Stack {
    private ListManager listManager;  // Stack์€ ListManager๋ฅผ ํ•ฉ์„ฑ (has-a)

    public Stack() {
        this.listManager = new ListManager();
    }

    public void push(String element) {
        listManager.addElement(element);  // ํ•„์š”ํ•œ ๊ธฐ๋Šฅ๋งŒ ์‚ฌ์šฉ
    }

    public void pop() {
        System.out.println("Element removed from stack.");
    }
}

public class Main {
    public static void main(String[] args) {
        Stack stack = new Stack();
        stack.push("item");
        stack.pop();
        // stack.addElement()๋Š” ํ˜ธ์ถœํ•  ์ˆ˜ ์—†์Œ
    }
}

์—ฌ๊ธฐ์„œ Stack์€ ListManager์˜ ๋‚ด๋ถ€ ๋™์ž‘ ์ค‘ ํ•„์š”ํ•œ ๋ฉ”์„œ๋“œ๋งŒ ๋…ธ์ถœํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋ฉฐ, ๋ถˆํ•„์š”ํ•œ ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ์ˆจ๊ธด๋‹ค.

  • ํ•ฉ์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ ๊ฐ์ฒด๋Š” ๋…๋ฆฝ์ ์œผ๋กœ ๊ด€๋ฆฌ๋˜๋ฉฐ, ๋ณ€๊ฒฝ์— ๋” ๊ฐ•ํ•œ ์„ค๊ณ„๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค.

5) ์—„๋ฐ€ํžˆ ๋ณด๋ฉด ํ•ฉ์„ฑ์ด๋ž‘ ์ปดํฌ์ง€์…˜๋„ ๋‹ค๋ฅด๋‹ค?

ํ˜ผ์šฉํ•ด์„œ ์“ฐ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋Œ€๋ถ€๋ถ„์ด๋ผ๊ณ  ํ•จ.. ํ•ฉ์„ฑ์ด๋ผ๊ณ  ํ•˜๋ฉด ์ปดํฌ์ง€์…˜์ด๋ผ๊ณ  ์ƒ๊ฐํ•ด๋„ ๋ฌด๋ฐฉํ•  ๋“ฏ ํ•˜๋‹ค.

์ปดํฌ์ง€์…˜(Composition)๊ณผ ํ•ฉ์„ฑ(Aggregation)์€ ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ๊ฐ์ฒด ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ๋‚˜ํƒ€๋‚ผ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ์ค‘์š”ํ•œ ๊ฐœ๋…๋“ค์ด๋‹ค. ๋‘ ๊ฐœ๋…์€ ์„œ๋กœ ์œ ์‚ฌํ•˜์ง€๋งŒ ์ค‘์š”ํ•œ ์ฐจ์ด์ ์ด ์žˆ์œผ๋ฉฐ, ๊ฐ๊ฐ์˜ ๊ฒฝ์šฐ์— ๋งž๋Š” ์ ์ ˆํ•œ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

์ปดํฌ์ง€์…˜(Composition)

  • ์˜๋ฏธ: ์ปดํฌ์ง€์…˜์€ ๊ฐ•ํ•œ ๊ด€๊ณ„๋ฅผ ๋œปํ•œ๋‹ค. ํ•œ ๊ฐ์ฒด๊ฐ€ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ํฌํ•จํ•˜๊ณ , ํฌํ•จ๋œ ๊ฐ์ฒด๋Š” ๋…๋ฆฝ์ ์œผ๋กœ ์กด์žฌํ•  ์ˆ˜ ์—†๋Š” ๊ด€๊ณ„์ด๋‹ค.
  • ์˜ˆ์‹œ: ์ž๋™์ฐจ(์ „์ฒด)๋Š” ์—”์ง„(๋ถ€๋ถ„)์„ ํฌํ•จํ•œ๋‹ค. ์—”์ง„์€ ์ž๋™์ฐจ์˜ ์ผ๋ถ€๋กœ, ์ž๋™์ฐจ๊ฐ€ ์—†์œผ๋ฉด ์—”์ง„์€ ์˜๋ฏธ๊ฐ€ ์—†๋‹ค. ์ฆ‰, ์ปดํฌ์ง€์…˜์—์„œ๋Š” ์ „์ฒด ๊ฐ์ฒด๊ฐ€ ์†Œ๋ฉธํ•˜๋ฉด ๋ถ€๋ถ„ ๊ฐ์ฒด๋„ ํ•จ๊ป˜ ์†Œ๋ฉธ๋œ๋‹ค.

์˜ˆ์‹œ ์ฝ”๋“œ:

class Car {
    private Engine engine;

    Car() {
        this.engine = new Engine(); // ์—”์ง„์„ ์ง์ ‘ ์ดˆ๊ธฐํ™”
    }

    void start() {
        engine.run();
    }
}

class Engine {
    void run() {
        System.out.println("Engine is running...");
    }
}
  • Car๋Š” Engine์„ ํฌํ•จํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, Car๊ฐ€ ์—†์–ด์ง€๋ฉด Engine๋„ ์˜๋ฏธ๋ฅผ ์žƒ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์ปดํฌ์ง€์…˜์˜ ์ „ํ˜•์ ์ธ ์˜ˆ

ํ•ฉ์„ฑ(Aggregation)

  • ์˜๋ฏธ: ํ•ฉ์„ฑ์€ ์•ฝํ•œ ๊ด€๊ณ„๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. ํ•˜๋‚˜์˜ ๊ฐ์ฒด๊ฐ€ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ์ง€๋งŒ, ๊ทธ ํฌํ•จ๋œ ๊ฐ์ฒด๋Š” ๋…๋ฆฝ์ ์œผ๋กœ ์กด์žฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰, ์ „์ฒด ๊ฐ์ฒด๊ฐ€ ์—†์–ด์ ธ๋„ ๋ถ€๋ถ„ ๊ฐ์ฒด๋Š” ์—ฌ์ „ํžˆ ์กด์žฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ด€๊ณ„์ด๋‹ค.
  • ์˜ˆ์‹œ: ํ•™๊ต(์ „์ฒด)๋Š” ํ•™์ƒ(๋ถ€๋ถ„)์„ ํฌํ•จํ•œ๋‹ค. ํ•˜์ง€๋งŒ ํ•™๊ต๊ฐ€ ์—†์–ด์ ธ๋„ ํ•™์ƒ์€ ์—ฌ์ „ํžˆ ์กด์žฌํ•  ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ์‹œ ์ฝ”๋“œ:

class School {
    private Student student;

    School(Student student) {
        this.student = student; // ์™ธ๋ถ€์—์„œ ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…๋ฐ›์Œ
    }

    void educate() {
        student.study();
    }
}

class Student {
    void study() {
        System.out.println("Student is studying...");
    }
}
  • School์€ Student๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ์ง€๋งŒ, Student ๊ฐ์ฒด๋Š” School์ด ์—†์–ด์ ธ๋„ ๋…๋ฆฝ์ ์œผ๋กœ ์กด์žฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํ•ฉ์„ฑ์˜ ์ „ํ˜•์ ์ธ ์˜ˆ

์ปดํฌ์ง€์…˜๊ณผ ํ•ฉ์„ฑ์˜ ์ฐจ์ด์  ์š”์•ฝ

ํ•ญ๋ชฉ์ปดํฌ์ง€์…˜(Composition)ํ•ฉ์„ฑ(Aggregation)
๊ด€๊ณ„๊ฐ•ํ•œ ๊ด€๊ณ„ (์ „์ฒด์™€ ๋ถ€๋ถ„์ด ๊ฐ•ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋จ)์•ฝํ•œ ๊ด€๊ณ„ (์ „์ฒด์™€ ๋ถ€๋ถ„์ด ๋…๋ฆฝ์ )
์ƒ๋ช… ์ฃผ๊ธฐ์ „์ฒด๊ฐ€ ์—†์–ด์ง€๋ฉด ๋ถ€๋ถ„๋„ ์—†์–ด์ง์ „์ฒด๊ฐ€ ์—†์–ด์ ธ๋„ ๋ถ€๋ถ„์€ ์กด์žฌํ•  ์ˆ˜ ์žˆ์Œ
๊ฐ์ฒด ์ƒ์„ฑ ๋ฐฉ์‹ํฌํ•จํ•˜๋Š” ๊ฐ์ฒด๊ฐ€ ์ง์ ‘ ๋ถ€๋ถ„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•จํฌํ•จํ•˜๋Š” ๊ฐ์ฒด๊ฐ€ ์™ธ๋ถ€์—์„œ ๋ถ€๋ถ„ ๊ฐ์ฒด๋ฅผ ๋ฐ›์•„์˜ด
์˜์กด์„ฑ์ „์ฒด ๊ฐ์ฒด์— ๊ฐ•ํ•˜๊ฒŒ ์˜์กด (๋…๋ฆฝ์ ์œผ๋กœ ์กด์žฌ ๋ถˆ๊ฐ€)์•ฝํ•œ ์˜์กด์„ฑ (๋ถ€๋ถ„ ๊ฐ์ฒด๋Š” ๋…๋ฆฝ์ ์œผ๋กœ ์กด์žฌ ๊ฐ€๋Šฅ)
์˜ˆ์‹œ์ž๋™์ฐจ์™€ ์—”์ง„ํ•™๊ต์™€ ํ•™์ƒ

ํ•ฉ์„ฑ์€ ๊ฐ์ฒด์ง€ํ–ฅ ์„ค๊ณ„์—์„œ ์ƒ์†์— ๋น„ํ•ด ๋” ์œ ์—ฐํ•˜๊ณ , ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์šฉ์ดํ•œ ๋ฐฉ๋ฒ•์ด๋‹ค. ํŠนํžˆ ๊ฐ์ฒด ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ๋” ์ž์œ ๋กญ๊ฒŒ ์„ค๊ณ„ํ•˜๊ณ , ๋ณ€๊ฒฝ์ด ์šฉ์ดํ•˜๋ฉฐ, ๋ถˆํ•„์š”ํ•œ ์˜์กด์„ฑ์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

3. ์ •๋ฆฌํ•ด๋ณด๋ฉด,

1) ํ˜„์—…์—์„œ๋Š” ๋ณดํ†ต ์ƒ์†์„ ์–ด๋–ป๊ฒŒ ์“ฐ๋ƒ..

๋ณดํ†ต ๋ณด๋‹ˆ๊นŒ ์˜ˆ๋ฅผ ๋“ค์–ด WebController - WebBaseController์ฒ˜๋Ÿผ ํด๋ž˜์Šค ์ด๋ฆ„๋ถ€ํ„ฐ is-a ๊ด€๊ณ„์ธ ์• ๋“ค๋งŒ ์ƒ์†์—์„œ ์“ฐ๋”๋ผ

2) ์ •๋ฆฌ ๐Ÿพ

  • ์ƒ์†์€ is-a ๊ด€๊ณ„์ผ ๋•Œ๋งŒ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ํด๋ž˜์Šค ๊ฐ„์˜ ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ํ˜•์„ฑํ•  ๋•Œ ๋ง์ด๋‹ค. ์ฆ‰, ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ์ƒ์œ„ ํด๋ž˜์Šค์˜ ์ง„์งœ ํ•˜์œ„ ํƒ€์ž…์ธ ๊ฒฝ์šฐ์—๋งŒ ์ƒ์†์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ๋‚ด๋ถ€ ๊ตฌํ˜„์— ์˜์กดํ•˜๊ฑฐ๋‚˜ ๊ฐ•ํ•œ ๊ฒฐํ•ฉ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค.
  • ์ปดํฌ์ง€์…˜์€ Has-a ๊ด€๊ณ„๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ํด๋ž˜์Šค์˜ ๊ธฐ๋Šฅ์„ ์œ ์—ฐํ•˜๊ฒŒ ํ™•์žฅํ•˜๊ณ  ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ปดํฌ์ง€์…˜๊ณผ ์œ„์ž„์„ ์‚ฌ์šฉํ•˜๋ฉด ์ƒ์†์˜ ๋‹จ์ ์„ ํ”ผํ•˜๋ฉด์„œ ์œ ์—ฐํ•˜๊ณ  ์•ˆ์ „ํ•˜๊ฒŒ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ๊ฒฐํ•ฉ๋„๊ฐ€ ๋‚ฎ์•„ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์šฉ์ดํ•˜์ง€๋งŒ, ๋‹คํ˜•์„ฑ ํ™œ์šฉ์ด ์ œํ•œ์ ์ผ ์ˆ˜ ์žˆ๋‹ค.
  • ๋ž˜ํผ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ธฐ์กด ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„์— ์˜์กดํ•˜์ง€ ์•Š๊ณ ๋„ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํŠนํžˆ, ์ƒ์œ„ ํด๋ž˜์Šค์— ์ƒˆ๋กœ์šด ๋ฉ”์„œ๋“œ๊ฐ€ ์ถ”๊ฐ€๋˜๋”๋ผ๋„ ํ•˜์œ„ ํด๋ž˜์Šค์˜ ๋™์ž‘์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋Š”๋‹ค.

์ƒ์†์„ ์ง€์–‘ํ•˜๊ณ  ํ•ฉ์„ฑ์„ ์ง€ํ–ฅํ•˜๋ผ๋Š” ๋ง์€, ์ƒ์†์€ ๋ฐ˜๋“œ์‹œ ์–ด๋– ํ•œ ํŠน์ •ํ•œ ๊ด€๊ณ„ ์ผ ๋•Œ๋งŒ ์‚ฌ์šฉํ•˜๋ผ๊ณ  ์—„๊ฒฉํ•˜๊ฒŒ ์ œํ•œํ•˜๋ผ๋Š” ๋ง์ด๋ฉฐ, ๊ทธ ๊ด€๊ณ„๊ฐ€ IS-A ๊ด€๊ณ„ ์ธ ๊ฒƒ์ด๋‹ค.

3) ์ƒ์†๊ณผ ํ•ฉ์„ฑ ๋น„๊ต

ํ•ญ๋ชฉ์ƒ์† (Inheritance)ํ•ฉ์„ฑ (Composition)
์˜์กด์„ฑ ํ•ด๊ฒฐ๋ถ€๋ชจ ํด๋ž˜์Šค์™€ ์ž์‹ ํด๋ž˜์Šค ์‚ฌ์ด์˜ ์˜์กด์„ฑ์€ ์ปดํŒŒ์ผ ํƒ€์ž„์— ํ•ด๊ฒฐ๋จ๋‘ ๊ฐ์ฒด ์‚ฌ์ด์˜ ์˜์กด์„ฑ์€ ๋Ÿฐํƒ€์ž„์— ํ•ด๊ฒฐ๋จ
๊ด€๊ณ„ ์œ ํ˜•"is-a" ๊ด€๊ณ„๋ฅผ ๋‚˜ํƒ€๋ƒ„"has-a" ๊ด€๊ณ„๋ฅผ ๋‚˜ํƒ€๋ƒ„
๊ฒฐํ•ฉ๋„๋ถ€๋ชจ ํด๋ž˜์Šค์™€ ์ž์‹ ํด๋ž˜์Šค ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๊ฐ€ ๋†’์Œํฌํ•จ๋œ ๊ฐ์ฒด ๋˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กดํ•˜๋ฏ€๋กœ ๊ฒฐํ•ฉ๋„๊ฐ€ ๋‚ฎ์Œ
์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์ž์‹ ํด๋ž˜์Šค๊ฐ€ ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ๊ตฌํ˜„์„ ์žฌ์‚ฌ์šฉํ•จํฌํ•จ๋œ ๊ฐ์ฒด๋‚˜ ์ธํ„ฐํŽ˜์ด์Šค์— ์ž‘์—…์„ ์œ„์ž„ํ•˜์—ฌ ์žฌ์‚ฌ์šฉํ•จ
์œ ์—ฐ์„ฑํด๋ž˜์Šค ๊ฐ„์˜ ๊ฒฐํ•ฉ์ด ๊ฐ•ํ•ด ์œ ์—ฐ์„ฑ์ด ๋–จ์–ด์ง๊ฐ์ฒด ๊ฐ„ ๊ฒฐํ•ฉ์ด ์•ฝํ•˜๊ณ  ์œ ์—ฐ์„ฑ์ด ๋†’์Œ
์ˆ˜์ • ์‹œ ์˜ํ–ฅ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ์ˆ˜์ •์ด ์ž์‹ ํด๋ž˜์Šค์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ์Œ๋‚ด๋ถ€์ ์œผ๋กœ ์ˆ˜์ •ํ•˜๊ธฐ ์šฉ์ดํ•˜๋ฉฐ, ์ข…์†์„ฑ๋„ ์ ์Œ

ํ•ฉ์„ฑ์€ ๋ณดํ†ต ๋” ์œ ์—ฐํ•˜๊ณ  ๋ชจ๋“ˆํ™”๊ฐ€ ์ž˜ ๋˜์–ด ์žˆ์œผ๋ฉฐ, ์ƒ์†์€ ์ž˜๋ชป ์‚ฌ์šฉํ•˜๋ฉด ๊ฒฐํ•ฉ๋„๊ฐ€ ๋†’์•„์ ธ ์˜ˆ๊ธฐ์น˜ ์•Š์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

โœ”๏ธ OOP์  ๊ด€์ ์—์„œ ๋ดค์„ ๋•Œ๋„ ์ƒ์†๋ณด๋‹ค๋Š” ์ปดํฌ์ง€์…˜์ด ๊ฐ์ฒด์˜ ์ž์œจ์„ฑ์„ ์ธ์ •ํ•˜๋ฉด์„œ๋„ ์•ˆ์ •์ ์ด๊ณ , ์บก์Šํ™”๋ฅผ ๋” ์ข‹๊ฒŒ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

4. ์ฝ”ํ‹€๋ฆฐ์—์„œ๋Š” ์ƒ์†์„ ์–ด๋–ค์‹์œผ๋กœ ํ•ด๊ฒฐํ•ด์คฌ์„๊นŒ?

๐Ÿ€ ์ฝ”ํ‹€๋ฆฐ์ด๋ž€

JetBrains์—์„œ ๊ฐœ๋ฐœํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋กœ, ์ฃผ๋กœ ์ž๋ฐ”๋ฅผ ๋Œ€์ฒดํ•˜๊ฑฐ๋‚˜ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์—ˆ๋‹ค. ์ฝ”ํ‹€๋ฆฐ์€ JVM(์ž๋ฐ” ๊ฐ€์ƒ ๋จธ์‹ )์—์„œ ์‹คํ–‰๋˜๋ฉฐ, ์ž๋ฐ”์™€ 100% ํ˜ธํ™˜๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ์กด ์ž๋ฐ” ํ”„๋กœ์ ํŠธ์—์„œ ๋ฌด๋ฆฌ ์—†์ด ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ์ฝ”ํ‹€๋ฆฐ์€ ์ž๋ฐ”์—์„œ ๋ถˆํŽธํ•œ ์ ์ด๋‚˜ ํ•œ๊ณ„์ ์„ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ์ค‘์ ์„ ๋‘์—ˆ์œผ๋ฉฐ, ์ž๋ฐ”๋ณด๋‹ค ๋” ๊ฐ„๊ฒฐํ•˜๊ณ  ์•ˆ์ „ํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

์ฝ”ํ‹€๋ฆฐ์˜ ๋„ ์•ˆ์ „์„ฑ, ๊ฐ„๊ฒฐํ•œ ๋ฌธ๋ฒ•, ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ง€์›, ์Šค๋งˆํŠธ ์บ์ŠคํŠธ, ์œ„์ž„, ์ฝ”๋ฃจํ‹ด ๋“ฑ์˜ ๊ธฐ๋Šฅ์€ ์ž๋ฐ”๋ณด๋‹ค ๋” ์•ˆ์ „ํ•˜๊ณ  ํšจ์œจ์ ์ธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐ ํฐ ๋„์›€์„ ์ค€๋‹ค.

๊ทธ๋ ‡๊ธฐ์— ์ž๋ฐ”์—์„œ ์ƒ์† ๋ฌธ์ œ๋ฅผ ์–ด๋Š ์ •๋„ ํ•ด๊ฒฐํ•ด์ค„ ๊ฑฐ๋ผ ์ƒ๊ฐํ•ด์„œ ์ฐพ์•„๋ณด๊ฒŒ ๋จ

๐Ÿ€ ์ฝ”ํ‹€๋ฆฐ์˜ ์ž๋ฐ”์—์„œ ์ƒ์† ๋ฌธ์ œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

์ฝ”ํ‹€๋ฆฐ(Kotlin)์—์„œ๋„ ์ž๋ฐ”์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ƒ์†์„ ์ง€์›ํ•˜์ง€๋งŒ, ์ƒ์†์— ๋”ฐ๋ฅธ ๋ฌธ์ œ๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•ด ๋ช‡ ๊ฐ€์ง€ ์–ธ์–ด์  ํŠน์„ฑ์„ ์ œ๊ณตํ•œ๋‹ค. ํŠนํžˆ, ์ƒ์†๊ณผ ๊ด€๋ จ๋œ ๋ฌธ์ œ๋ฅผ ์˜ˆ๋ฐฉํ•˜๊ฑฐ๋‚˜ ์™„ํ™”ํ•˜๊ธฐ ์œ„ํ•œ ์ฝ”ํ‹€๋ฆฐ์˜ ์„ค๊ณ„ ์ฒ ํ•™์€ ์ž๋ฐ”๋ณด๋‹ค ์—„๊ฒฉํ•˜๊ณ  ๋” ์•ˆ์ „ํ•œ ๋ฐฉํ–ฅ์œผ๋กœ ๋‚˜์•„๊ฐ€ ์žˆ๋‹ค. ์ด๋Ÿฐ ํŠน์ง•๋“ค์ด ์ž๋ฐ”์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์ƒ์† ๋ฌธ์ œ๋“ค์„ ์ผ๋ถ€ ํ•ด๊ฒฐํ•ด์ค€๋‹ค.

1) ๊ธฐ๋ณธ์ ์œผ๋กœ ํด๋ž˜์Šค๊ฐ€ final

  • ์ฝ”ํ‹€๋ฆฐ์—์„œ๋Š” ๋ชจ๋“  ํด๋ž˜์Šค๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ final๋กœ ์„ ์–ธ๋œ๋‹ค. ์ฆ‰, ๋ช…์‹œ์ ์œผ๋กœ open ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํ•œ ํด๋ž˜์Šค๋Š” ์ƒ์†์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

    ์ž๋ฐ” ์˜ˆ์‹œ:

    class Animal {
        public void makeSound() {
            System.out.println("Animal makes a sound");
        }
    }
    
    class Dog extends Animal {
        @Override
        public void makeSound() {
            System.out.println("Dog barks");
        }
    }

    ์ฝ”ํ‹€๋ฆฐ ์˜ˆ์‹œ:

    open class Animal {
        open fun makeSound() {
            println("Animal makes a sound")
        }
    }
    
    class Dog : Animal() {
        override fun makeSound() {
            println("Dog barks")
        }
    }

    ์ฝ”ํ‹€๋ฆฐ์—์„œ๋Š” ์ƒ์†์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์œผ๋ฉด open ํ‚ค์›Œ๋“œ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์„ ์–ธํ•ด์•ผ ํ•œ๋‹ค. ์ด๋Š” ์ƒ์†์˜ ๋‚จ์šฉ์„ ์ค„์ด๊ณ , ๋ถˆํ•„์š”ํ•œ ์ƒ์†์„ ํ†ตํ•œ ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ค€๋‹ค.

2) sealed ํด๋ž˜์Šค

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

    ์ฝ”ํ‹€๋ฆฐ ์˜ˆ์‹œ:

    sealed class Animal {
        class Dog : Animal()
        class Cat : Animal()
    }

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

3) data ํด๋ž˜์Šค

  • data ํด๋ž˜์Šค๋Š” ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฅผ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค. ์ด๋Š” ์ƒ์†๋ณด๋‹ค ์กฐํ•ฉ(Composition)์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉํ–ฅ์„ ์žฅ๋ คํ•˜๋ฉฐ, ๋ถˆํ•„์š”ํ•œ ์ƒ์† ์—†์ด๋„ ๊ฐ์ฒด์˜ ๊ธฐ๋Šฅ์„ ์‰ฝ๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

    ์ฝ”ํ‹€๋ฆฐ ์˜ˆ์‹œ:

    data class Person(val name: String, val age: Int)

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

4) ์ธํ„ฐํŽ˜์ด์Šค์™€ default ๋ฉ”์„œ๋“œ ๋ฌธ์ œ ํ•ด๊ฒฐ

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

5) ์ฝ”ํ‹€๋ฆฐ์˜ by ํ‚ค์›Œ๋“œ๋กœ ์œ„์ž„(Delegation)

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

    ์ฝ”ํ‹€๋ฆฐ ์˜ˆ์‹œ:

    interface Sound {
        fun makeSound()
    }
    
    class Dog : Sound {
        override fun makeSound() {
            println("Dog barks")
        }
    }
    
    class Cat : Sound {
        override fun makeSound() {
            println("Cat meows")
        }
    }
    
    class Animal(sound: Sound) : Sound by sound

์ด๋ž˜์„œ ๋‹ค๋“ค.. ์ฝ”ํ‹€๋ฆฐ ์ฝ”ํ‹€๋ฆฐ ํ•˜๋Š” ๊ฑด๊ฐ€ ์‹ถ์Œ...

๐Ÿ“Ž ์ฐธ๊ณ  ๊ธ€

profile
๋‚ด ์ง€์‹์„ ๊ธฐ๋กํ•˜์—ฌ, ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค๊ณผ ๊ณต์œ ํ•˜์—ฌ ํ•จ๊ป˜ ๋ฐœ์ „ํ•˜๋Š” ์‚ฌ๋žŒ์ด ๋˜๊ณ  ์‹ถ๋‹ค. gitbook์—๋„ ์ •๋ฆฌ์ค‘ ~

0๊ฐœ์˜ ๋Œ“๊ธ€