본문으둜 κ±΄λ„ˆλ›°κΈ°

🌈 Chapter 13: μ„œλΈŒν΄λž˜μ‹±κ³Ό μ„œλΈŒνƒ€μ΄ν•‘

  • μƒμ†μ˜ 첫 번째 μš©λ„λŠ” νƒ€μž… 계측을 κ΅¬ν˜„ν•˜λŠ” 것이닀. νƒ€μž… κ³„μΈ΅μ˜ κ΄€μ μ—μ„œ λΆ€λͺ¨ ν΄λž˜μŠ€λŠ” μžμ‹ 클래슀의 μΌλ°˜ν™”μ΄κ³  μžμ‹ ν΄λž˜μŠ€λŠ” λΆ€λͺ¨ 클래슀의 νŠΉμˆ˜ν™”λ‹€.
  • μƒμ†μ˜ 두 번째 μš©λ„λŠ” μ½”λ“œ μž¬μ‚¬μš©μ΄λ‹€. 상속을 μ‚¬μš©ν•˜λ©΄ μ μ§„μ μœΌλ‘œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ κΈ°λŠ₯을 ν™•μž₯ν•  수 μžˆλ‹€. ν•˜μ§€λ§Œ μž¬μ‚¬μš©μ„ μœ„ν•΄ 상속을 μ‚¬μš©ν•  경우 λΆ€λͺ¨ ν΄λž˜μŠ€μ™€ μžμ‹ ν΄λž˜μŠ€κ°€ κ°•ν•˜κ²Œ κ²°ν•©λ˜κΈ° λ•Œλ¬Έμ— λ³€κ²½ν•˜κΈ° μ–΄λ €μš΄ μ½”λ“œλ₯Ό μ–»κ²Œ 될 ν™•λ₯ μ΄ λ†’λ‹€.
  • 상속을 μ‚¬μš©ν•˜λŠ” 일차적인 λͺ©ν‘œλŠ” μ½”λ“œ μž¬μ‚¬μš©μ΄ μ•„λ‹ˆλΌ νƒ€μž… 계측을 κ΅¬ν˜„ν•˜λŠ” 것이어야 ν•œλ‹€. νƒ€μž… 계측을 λͺ©ν‘œλ‘œ 상속을 μ‚¬μš©ν•˜λ©΄ λ‹€ν˜•μ μœΌλ‘œ λ™μž‘ν•˜λŠ” κ°μ²΄λ“€μ˜ 관계에 κΈ°λ°˜ν•΄ ν™•μž₯ κ°€λŠ₯ν•˜κ³  μœ μ—°ν•œ 섀계λ₯Ό 얻을 수 있게 λœλ‹€.
  • νƒ€μž… μ‚¬μ΄μ˜ 관계λ₯Ό κ³ λ €ν•˜μ§€ μ•Šμ€ 채 λ‹¨μˆœνžˆ μ½”λ“œλ₯Ό μž¬μ‚¬μš©ν•˜κΈ° μœ„ν•΄ 상속을 μ‚¬μš©ν•΄μ„œλŠ” μ•ˆ λœλ‹€.

πŸ“š νƒ€μž…β€‹

🎈 κ°œλ… κ΄€μ μ˜ νƒ€μž…β€‹

  • κ°œλ… κ΄€μ μ—μ„œ νƒ€μž…μ΄λž€ μš°λ¦¬κ°€ μΈμ§€ν•˜λŠ” μ„Έμƒμ˜ μ‚¬λ¬Όμ˜ μ’…λ₯˜λ₯Ό μ˜λ―Έν•œλ‹€. λ‹€μ‹œ 말해 μš°λ¦¬κ°€ μΈμ‹ν•˜λŠ” 객체듀에 μ μš©ν•˜λŠ” κ°œλ…μ΄λ‚˜ 아이디어λ₯Ό κ°€λ¦¬μΌœ νƒ€μž…μ΄λΌκ³  λΆ€λ₯Έλ‹€. νƒ€μž…μ€ 사물을 λΆ„λ₯˜ν•˜κΈ° μœ„ν•œ ν‹€λ‘œ μ‚¬μš©λœλ‹€.
  • 예λ₯Ό λ“€μ–΄, μžλ°”, 루비, μžλ°”μŠ€ν¬λ¦½νŠΈ, Cλ₯Ό ν”„λ‘œκ·Έλž˜λ° 언어라고 λΆ€λ₯Ό λ•Œ 이것듀을 ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄λΌλŠ” νƒ€μž…μœΌλ‘œ λΆ„λ₯˜ν•˜κ³  μžˆλŠ” 것이닀.
  • μ–΄λ–€ λŒ€μƒμ΄ νƒ€μž…μœΌλ‘œ λΆ„λ₯˜λ  λ•Œ κ·Έ λŒ€μƒμ„ νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€λΌκ³  λΆ€λ₯Έλ‹€. (μžλ°”, 루비, μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ˜ μΈμŠ€ν„΄μŠ€λ‹€.) 일반적으둜 νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό 객체라고 λΆ€λ₯Έλ‹€.
  • 심볼(symbol)μ΄λž€ νƒ€μž…μ— 이름을 뢙인 것이닀. (ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄κ°€ νƒ€μž…μ˜ 심볼에 ν•΄λ‹Ήν•œλ‹€.)
  • λ‚΄μ—°(intension)μ΄λž€ νƒ€μž…μ˜ μ •μ˜λ‘œμ„œ νƒ€μž…μ— μ†ν•˜λŠ” 객체듀이 κ°€μ§€λŠ” 곡톡적인 μ†μ„±μ΄λ‚˜ 행동을 가리킨닀. (ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ˜ μ •μ˜μΈ μ»΄ν“¨ν„°μ—κ²Œ νŠΉμ •ν•œ μž‘μ—…μ„ μ§€μ‹œν•˜κΈ° μœ„ν•œ μ–΄νœ˜μ™€ 문법적 κ·œμΉ™μ˜ 집합)
  • μ™Έμ—°(extension)μ΄λž€ νƒ€μž…μ— μ†ν•˜λŠ” κ°μ²΄λ“€μ˜ 집합이닀. (μžλ°”, 루비, μžλ°”μŠ€ν¬λ¦½νŠΈ, C)

🎈 ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄ κ΄€μ μ˜ νƒ€μž…β€‹

  • ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ˜ κ΄€μ μ—μ„œ νƒ€μž…μ€ λΉ„νŠΈ λ¬ΆμŒμ— 의미λ₯Ό λΆ€μ—¬ν•˜κΈ° μœ„ν•΄ μ •μ˜λœ μ œμ•½κ³Ό κ·œμΉ™μ„ 가리킨닀.
  • ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ—μ„œ νƒ€μž…μ€ 두 가지 λͺ©μ μ„ μœ„ν•΄ μ‚¬μš©λœλ‹€.
    • νƒ€μž…μ— μˆ˜ν–‰λ  수 μžˆλŠ” μœ νš¨ν•œ μ˜€νΌλ ˆμ΄μ…˜μ˜ 집합을 μ •μ˜ν•œλ‹€.
    • νƒ€μž…μ— μˆ˜ν–‰λ˜λŠ” μ˜€νΌλ ˆμ΄μ…˜μ— λŒ€ν•΄ 미리 μ•½μ†λœ λ¬Έλ§₯을 μ œκ³΅ν•œλ‹€.
  • μ •λ¦¬ν•˜λ©΄ νƒ€μž…μ€ 적용 κ°€λŠ₯ν•œ μ˜€νΌλ ˆμ΄μ…˜μ˜ μ’…λ₯˜μ™€ 의미λ₯Ό μ •μ˜ν•¨μœΌλ‘œμ¨ μ½”λ“œμ˜ 의미λ₯Ό λͺ…ν™•ν•˜κ²Œ μ „λ‹¬ν•˜κ³  개발자의 μ‹€μˆ˜λ₯Ό λ°©μ§€ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λœλ‹€.

🎈 객체지ν–₯ νŒ¨λŸ¬λ‹€μž„ κ΄€μ μ˜ νƒ€μž…β€‹

  • κ°œλ… κ΄€μ μ—μ„œ νƒ€μž…μ΄λž€ κ³΅ν†΅μ˜ νŠΉμ§•μ„ κ³΅μœ ν•˜λŠ” λŒ€μƒλ“€μ˜ λΆ„λ₯˜λ‹€.
  • ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄ κ΄€μ μ—μ„œ νƒ€μž…μ΄λž€ λ™μΌν•œ μ˜€νΌλ ˆμ΄μ…˜μ„ μ μš©ν•  수 μžˆλŠ” μΈμŠ€ν„΄μŠ€λ“€μ˜ 집합이닀.
  • ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ˜ κ΄€μ μ—μ„œ 호좜 κ°€λŠ₯ν•œ μ˜€νΌλ ˆμ΄μ…˜μ˜ 집합을 μ •μ˜ν•œλ‹€. 객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ—μ„œ μ˜€νΌλ ˆμ΄μ…˜μ€ 객체가 μˆ˜μ‹ ν•  수 μžˆλŠ” λ©”μ‹œμ§€λ₯Ό μ˜λ―Έν•œλ‹€. λ”°λΌμ„œ 객체의 νƒ€μž…μ΄λž€ 객체가 μˆ˜μ‹ ν•  수 μžˆλŠ” λ©”μ‹œμ§€μ˜ μ’…λ₯˜λ₯Ό μ •μ˜ν•˜λŠ” 것이닀.
  • 객체가 μˆ˜μ‹ ν•  수 μžˆλŠ” λ©”μ‹œμ§€μ˜ 집합을 κ°€λ¦¬ν‚€λŠ” μš©μ–΄λ‘œ 퍼블릭 μΈν„°νŽ˜μ΄μŠ€κ°€ 그것이닀. 즉, 객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ—μ„œ νƒ€μž…μ„ μ •μ˜ν•˜λŠ” 것은 객체의 퍼블릭 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ •μ˜ν•˜λŠ” 것과 λ™μΌν•˜λ‹€.
  • 객체지ν–₯μ—μ„œ 객체가 μˆ˜μ‹ ν•  수 μžˆλŠ” λ©”μ‹œμ§€λ₯Ό κΈ°μ€€μœΌλ‘œ νƒ€μž…μ„ λΆ„λ₯˜ν•˜κΈ° λ•Œλ¬Έμ— λ™μΌν•œ 퍼블릭 μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ°€μ§€λŠ” 객체듀은 λ™μΌν•œ νƒ€μž…μœΌλ‘œ λΆ„λ₯˜ν•  수 μžˆλ‹€.

πŸ“š νƒ€μž… 계측​

🎈 νƒ€μž… μ‚¬μ΄μ˜ 포함관계​

  • νƒ€μž…μ€ κ°μ²΄λ“€μ˜ 집합이기 λ•Œλ¬Έμ— λ‹€λ₯Έ νƒ€μž…μ„ ν¬ν•¨ν•˜λŠ” 것이 κ°€λŠ₯ν•˜λ‹€.
  • νƒ€μž… μ•ˆμ— ν¬ν•¨λœ 객체듀을 μ’€ 더 μƒμ„Έν•œ κΈ°μ€€μœΌλ‘œ λ¬Άμ–΄ μƒˆλ‘œμš΄ νƒ€μž…μ„ μ •μ˜ν•˜λ©΄ 이 μƒˆλ‘œμš΄ νƒ€μž…μ€ μžμ—°μŠ€λŸ½κ²Œ κΈ°μ‘΄ νƒ€μž…μ˜ 뢀뢄집합이 λœλ‹€.
  • 예λ₯Ό λ“€μ–΄ μžλ°”, 루비, μžλ°”μŠ€ν¬λ¦½νŠΈ CλŠ” ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄ νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€μ΄λ―€λ‘œ ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄ μ§‘ν•©μ˜ μ›μ†Œλ‘œ ν‘œν˜„ν•  수 μžˆλ‹€. 이 μ§‘ν•©μ˜ μ›μ†Œλ₯Ό 더 μƒμ„Έν•˜κ²Œ λΆ„λ₯˜ν•  수 μžˆλ‹€. μžλ°”, 루비, μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” 객체지ν–₯ μ–Έμ–΄κ³  CλŠ” 절차적 μ–Έμ–΄λ‘œ λΆ„λ₯˜ν•  수 μžˆλ‹€. 더 λ‚˜μ•„κ°€ μžλ°”μ™€ λ£¨λΉ„λŠ” 클래슀 기반 μ–Έμ–΄λ‘œ, μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” ν”„λ‘œν† νƒ€μž… 기반 μ–Έμ–΄λ‘œ λΆ„λ₯˜ν•  수 μžˆλ‹€.
  • μ—¬κΈ°μ„œ μžλ°”λŠ” ν”„λ‘œκ·Έλž˜λ° 언어인 λ™μ‹œμ— 객체지ν–₯ 언어에 μ†ν•˜λ©° 더 μ„ΈλΆ€μ μœΌλ‘œ 클래슀 기반 μ–Έμ–΄ νƒ€μž…μ— μ†ν•˜κ²Œ λ˜λŠ” 것이닀.
  • λ‹€λ₯Έ νƒ€μž…μ„ ν¬ν•¨ν•˜λŠ” νƒ€μž…μ€ ν¬ν•¨ν•˜λŠ” νƒ€μž…λ³΄λ‹€ μ’€ 더 μΌλ°˜ν™”λœ 의미λ₯Ό ν‘œν˜„ν•  수 μžˆλ‹€. 반면 ν¬ν•¨λ˜λŠ” νƒ€μž…μ€ μ’€ 더 νŠΉμˆ˜ν•˜κ³  ꡬ체적이닀.
  • λ‹€λ₯Έ νƒ€μž…μ„ ν¬ν•¨ν•˜λŠ” νƒ€μž…μ€ ν¬ν•¨λ˜λŠ” νƒ€μž…λ³΄λ‹€ 더 λ§Žμ€ μΈμŠ€ν„΄μŠ€λ₯Ό 가진닀.
  • λ‹€μ‹œ λ§ν•΄μ„œ ν¬ν•¨λ˜λŠ” νƒ€μž…μ€ μ™Έμ—° κ΄€μ μ—μ„œλŠ” 더 크고 λ‚΄μ—° κ΄€μ μ—μ„œλŠ” 더 μΌλ°˜μ μ΄λ‹€. 이와 λ°˜λŒ€λ‘œ ν¬ν•¨λ˜λŠ” νƒ€μž…μ€ μ™Έμ—° κ΄€μ μ—μ„œλŠ” 더 μž‘κ³  λ‚΄μ—° κ΄€μ μ—μ„œλŠ” 더 νŠΉμˆ˜ν•˜λ‹€. 이것은 포함 κ΄€κ³„λ‘œ μ—°κ²°λœ νƒ€μž… 사이에 κ°œλ…μ μœΌλ‘œ μΌλ°˜ν™”μ™€ νŠΉμˆ˜ν™” 관계가 μ‘΄μž¬ν•œλ‹€λŠ” 것을 μ˜λ―Έν•œλ‹€.
  • νƒ€μž… 계측을 κ΅¬μ„±ν•˜λŠ” 두 νƒ€μž… κ°„μ˜ κ΄€μ μ—μ„œ 더 일반적인 νƒ€μž…μ„ μŠˆνΌνƒ€μž…(supertype)이라고 λΆ€λ₯΄κ³  더 νŠΉμˆ˜ν•œ νƒ€μž…μ„ μ„œλΈŒνƒ€μž…(subtype)이라고 λΆ€λ₯Έλ‹€.
  • 객체의 μ •μ˜λ₯Ό μ˜λ―Έν•˜λŠ” λ‚΄μ—° κ΄€μ μ—μ„œ μΌλ°˜ν™”λž€ μ–΄λ–€ νƒ€μž…μ˜ μ •μ˜λ₯Ό μ’€ 더 보편적이고 μΆ”μƒμ μœΌλ‘œ λ§Œλ“œλŠ” 과정을 μ˜λ―Έν•œλ‹€. λ°˜λŒ€λ‘œ νŠΉμˆ˜ν™”λž€ μ–΄λ–€ νƒ€μž…μ˜ μ •μ˜λ₯Ό μ’€ 더 ꡬ체적이고 λ¬Έλ§₯ μ’…μ†μ μœΌλ‘œ λ§Œλ“œλŠ” 과정을 μ˜λ―Έν•œλ‹€.
  • 집합을 μ˜λ―Έν•˜λŠ” μ™Έμ—°μ˜ κ΄€μ μ—μ„œ 일반적인 νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€ 집합은 νŠΉμˆ˜ν•œ νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€ 집합을 ν¬ν•¨ν•˜λŠ” μŠˆνΌμ…‹μ΄λ‹€. λ°˜λŒ€λ‘œ νŠΉμˆ˜ν•œ νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€ 집합은 일반적인 νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€ 집합에 ν¬ν•¨λœ μ„œλΈŒμ…‹μ΄λ‹€. λ”°λΌμ„œ νŠΉμˆ˜ν•œ νƒ€μž…μ— μ†ν•œ μΈμŠ€ν„΄μŠ€λŠ” λ™μ‹œμ— 더 일반적인 νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€μ΄κΈ°λ„ ν•˜λ‹€.
  • μΌλ°˜ν™”λŠ” λ‹€λ₯Έ νƒ€μž…μ„ μ™„μ „νžˆ ν¬ν•¨ν•˜κ±°λ‚˜ λ‚΄ν¬ν•˜λŠ” νƒ€μž…μ„ μ‹λ³„ν•˜λŠ” ν–‰μœ„ λ˜λŠ” κ·Έ ν–‰μœ„μ˜ κ²°κ³Όλ₯Ό 가리킨닀.
  • νŠΉμˆ˜ν™”λŠ” λ‹€λ₯Έ νƒ€μž… μ•ˆμ— μ „μ²΄μ μœΌλ‘œ ν¬ν•¨λ˜κ±°λ‚˜ μ™„μ „νžˆ λ‚΄ν¬λ˜λŠ” νƒ€μž…μ„ μ‹λ³„ν•˜λŠ” ν–‰μœ„ λ˜λŠ” κ·Έ ν–‰μœ„μ˜ κ²°κ³Όλ₯Ό 가리킨닀.
  • λ‚΄μ—°κ³Ό μ™Έμ—° κ΄€μ μ—μ„œ μ„œλΈŒνƒ€μž…κ³Ό μŠˆνΌνƒ€μž…μ„ λ‹€μŒκ³Ό 같이 μ •μ˜ν•  수 μžˆλ‹€.
    • μŠˆνΌνƒ€μž…μ€ λ‹€μŒκ³Ό 같은 νŠΉμ§•μ„ κ°€μ§€λŠ” νƒ€μž…μ„ 가리킨닀.
      • 집합이 λ‹€λ₯Έ μ§‘ν•©μ˜ λͺ¨λ“  멀버λ₯Ό ν¬ν•¨ν•œλ‹€.
      • νƒ€μž… μ •μ˜κ°€ λ‹€λ₯Έ νƒ€μž…λ³΄λ‹€ μ’€ 더 μΌλ°˜μ μ΄λ‹€.
    • μ„œλΈŒνƒ€μž…μ€ λ‹€μŒκ³Ό 같은 νŠΉμ§•μ„ κ°€μ§€λŠ” νƒ€μž…μ„ 가리킨닀.
      • 집합에 ν¬ν•¨λ˜λŠ” μΈμŠ€ν„΄μŠ€λ“€μ΄ 더 큰 집합에 ν¬ν•¨λœλ‹€.
      • νƒ€μž… μ •μ˜κ°€ λ‹€λ₯Έ νƒ€μž…λ³΄λ‹€ μ’€ 더 ꡬ체적이닀.

🎈 객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°κ³Ό νƒ€μž… 계측​

  • 객체의 νƒ€μž…μ„ κ²°μ •ν•˜λŠ” 것은 퍼블릭 μΈν„°νŽ˜μ΄μŠ€λ‹€.
  • 일반적인 νƒ€μž…μ΄λž€ λΉ„κ΅ν•˜λ €λŠ” νƒ€μž…μ— μ†ν•œ κ°μ²΄λ“€μ˜ 퍼블릭 μΈν„°νŽ˜μ΄μŠ€λ³΄λ‹€ 더 일반적인 퍼블릭 μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ°€μ§€λŠ” κ°μ²΄λ“€μ˜ νƒ€μž…μ„ μ˜λ―Έν•œλ‹€.
  • νŠΉμˆ˜ν•œ νƒ€μž…μ΄λž€ λΉ„κ΅ν•˜λ €λŠ” νƒ€μž…μ— μ†ν•œ κ°μ²΄λ“€μ˜ 퍼블릭 μΈν„°νŽ˜μ΄μŠ€λ³΄λ‹€ 더 νŠΉμˆ˜ν•œ 퍼블릭 μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ°€μ§€λŠ” κ°μ²΄λ“€μ˜ νƒ€μž…μ„ μ˜λ―Έν•œλ‹€.
  • μŠˆνΌνƒ€μž…μ΄λž€ μ„œλΈŒνƒ€μž…μ΄ μ •μ˜ν•œ 퍼블릭 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μΌλ°˜ν™”μ‹œμΌœ μƒλŒ€μ μœΌλ‘œ λ²”μš©μ μ΄κ³  넓은 의미둜 μ •μ˜ν•œ 것이닀.
  • μ„œλΈŒνƒ€μž…μ΄λž€ μŠˆνΌνƒ€μž…μ΄ μ •μ˜ν•œ 퍼블릭 μΈν„°νŽ˜μ΄μŠ€λ₯Ό νŠΉμˆ˜ν™”μ‹œμΌœ μƒλŒ€μ μœΌλ‘œ ꡬ체적이고 쒁은 의미둜 μ •μ˜ν•œ 것이닀.
  • μ„œλΈŒνƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€λŠ” μŠˆνΌνƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€λ‘œ 간주될 수 μžˆλ‹€.

πŸ“š μ„œλΈŒν΄λž˜μ‹±κ³Ό μ„œλΈŒνƒ€μ΄ν•‘β€‹

🎈 μ–Έμ œ 상속을 μ‚¬μš©ν•΄μ•Ό ν•˜λŠ”κ°€?​

  • λ‹€μŒ 두 μ§ˆλ¬Έμ— λͺ¨λ‘ 예라고 λ‹΅ν•  수 μžˆλŠ” κ²½μš°μ—λ§Œ 상속을 μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.
    • 상속 관계가 is-a 관계λ₯Ό λͺ¨λΈλ§ν•˜λŠ”κ°€? (μžμ‹ ν΄λž˜μŠ€λŠ” λΆ€λͺ¨ν΄λž˜μŠ€λ‹€.)
    • ν΄λΌμ΄μ–ΈνŠΈ μž…μž₯μ—μ„œ λΆ€λͺ¨ 클래슀의 νƒ€μž…μœΌλ‘œ μžμ‹ν΄λž˜μŠ€λ₯Ό μ‚¬μš©ν•΄λ„ λ¬΄λ°©ν•œκ°€? (상속 계측을 μ‚¬μš©ν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈμ˜ μž…μž₯μ—μ„œ λΆ€λͺ¨ ν΄λž˜μŠ€μ™€ μžμ‹ 클래슀의 차이점을 λͺ°λΌμ•Ό ν•œλ‹€. 이 λ‘˜ μ‚¬μ΄μ˜ 행동 ν˜Έν™˜μ„±μ΄λΌ λΆ€λ₯Έλ‹€.)

🎈 is-a 관계​

  • μ–΄λ–€ νƒ€μž… Sκ°€ λ‹€λ₯Έ νƒ€μž… T의 일쒅이라면 λ‹Ήμ—°νžˆ νƒ€μž… SλŠ” νƒ€μž… T닀라고 말할 수 μžˆμ–΄μ•Ό ν•œλ‹€. (객체지ν–₯ μ–Έμ–΄λŠ” ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄λ‹€.)
  • ν•˜μ§€λ§Œ is-a관계가 직관적이고 λͺ…μΎŒν•œ 것은 μ•„λ‹ˆλ‹€.
    • νŽ­κ·„μ€ μƒˆλ‹€.
    • μƒˆλŠ” λ‚  수 μžˆλ‹€.
public class Bird {
public void fiy() {...}
}

public class Penguin extends Bird { // νŽ­κ·„μ€ λ‚  수 μ—†λ‹€.
// ...
}
  • 이 μ˜ˆλŠ” μ–΄νœ˜μ μΈ μ •μ˜κ°€ μ•„λ‹ˆλΌ κΈ°λŒ€λ˜λŠ” 행동에 따라 νƒ€μž… 계측을 ꡬ성해야 ν•œλ‹€λŠ” 사싀을 잘 보여쀀닀.
  • λ”°λΌμ„œ νƒ€μž… κ³„μΈ΅μ˜ μ˜λ―ΈλŠ” ν–‰λ™μ΄λΌλŠ” λ¬Έλ§₯에 따라 λ‹¬λΌμ§ˆ 수 μžˆλ‹€. 그에 따라 μ˜¬λ°”λ₯Έ νƒ€μž… κ³„μΈ΅μ΄λΌλŠ” 의미 μ—­μ‹œ λ¬Έλ§₯에 따라 λ‹¬λΌμ§ˆ 수 μžˆλ‹€. λ”°λΌμ„œ μŠˆνΌνƒ€μž…κ³Ό μ„œλΈŒνƒ€μž… κ΄€κ³„μ—μ„œλŠ” is-a보닀 행동 ν˜Έν™˜μ„±μ΄ 더 μ€‘μš”ν•˜λ‹€.

🎈 행동 ν˜Έν™˜μ„±β€‹

  • νƒ€μž…μ˜ 이름 사이에 κ°œλ…μ μœΌλ‘œ μ–΄λ–€ 연관성이 μžˆλ‹€κ³  ν•˜λ”λΌλ„ 행동에 연관성이 μ—†λ‹€λ©΄ is-a관계λ₯Ό μ‚¬μš©ν•˜μ§€ 말아야 ν•œλ‹€.
  • 두 νƒ€μž… 사이에 행동이 ν˜Έν™˜λ  κ²½μš°μ—λ§Œ νƒ€μž… κ³„μΈ΅μœΌλ‘œ λ¬Άμ–΄μ•Ό ν•œλ‹€. ν–‰λ™μ˜ ν˜Έν™˜ μ—¬λΆ€λ₯Ό νŒλ‹¨ν•˜λŠ” 기쀀은 ν΄λΌμ΄μ–ΈνŠΈμ˜ 관점이닀. ν΄λΌμ΄μ–ΈνŠΈκ°€ 두 νƒ€μž…μ΄ λ™μΌν•˜κ²Œ 행동할 것이라고 κΈ°λŒ€ν•œλ‹€λ©΄ 두 νƒ€μž…μ„ νƒ€μž… κ³„μΈ΅μœΌλ‘œ 묢을 수 μžˆλ‹€. νƒ€μž… 계측을 μ΄ν•΄ν•˜κΈ° μœ„ν•΄μ„œλŠ” κ·Έ νƒ€μž… 계측이 μ‚¬μš©λ  λ¬Έλ§₯을 μ΄ν•΄ν•˜λŠ” 것이 μ€‘μš”ν•˜λ‹€.
  • λ‹€μŒκ³Ό 같이 ν΄λΌμ΄μ–ΈνŠΈκ°€ λ‚  수 μžˆλŠ” μƒˆλ§Œμ„ μ›ν•œλ‹€κ³  κ°€μ •ν•΄λ³Έλ‹€.
public void flyBird(Bird bird) {
// 인자둜 μ „λ‹¬λœ λͺ¨λ“  birdλŠ” λ‚  수 μžˆμ–΄μ•Ό ν•œλ‹€.
bird.fly();
}
  • Penguin은 ν΄λΌμ΄μ–ΈνŠΈμ˜ κΈ°λŒ€λ₯Ό 저버리기 λ•Œλ¬Έμ— Bird의 μ„œλΈŒνƒ€μž…μ΄ μ•„λ‹ˆλ‹€. λ”°λΌμ„œ 이 λ‘˜μ„ 상속 κ΄€κΌλ‘œ μ—°κ²°ν•œ μœ„ μ„€κ³„λŠ” μˆ˜μ •λΌμ•Ό ν•œλ‹€. 상속 관계λ₯Ό μœ μ§€ν•˜λ©΄μ„œ 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ μ‹œλ„ν•΄ λ³Ό 수 μžˆλŠ” μ„Έ 가지 방법이 μžˆλ‹€.
  • 첫 번째 방법은 Penguin의 fly λ©”μ„œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ”©ν•΄μ„œ λ‚΄λΆ€ κ΅¬ν˜„μ„ λΉ„μ›Œλ‘λŠ” 것이닀.
public class Penguin extends Bird {
// ...
@Override
public void fly() {}
}
  • ν•˜μ§€λ§Œ 이 방법은 μ–΄λ–€ 행동도 μˆ˜ν–‰ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— λͺ¨λ“  birdκ°€ λ‚  수 μžˆλ‹€λŠ” ν΄λΌμ΄μ–ΈνŠΈμ˜ κΈ°λŒ€λ₯Ό λ§Œμ‘±μ‹œν‚€μ§€ λͺ»ν•œλ‹€. λ”°λΌμ„œ μ˜¬λ°”λ₯Έ 섀계가 μ•„λ‹ˆλ‹€.
  • 두 번째 방법은 Penguin의 fly λ©”μ„œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ”©ν•œ ν›„ μ˜ˆμ™Έλ₯Ό λ˜μ§„λ‹€.
public class Penguin extends Bird {
// ...
@Override
public void fly() {
throw new UnsupportedOperationException();
}
}
  • ν•˜μ§€λ§Œ 이 κ²½μš°μ—λŠ” flyBird λ©”μ„œλ“œμ— μ „λ‹¬λ˜λŠ” 인자λ₯Ό νƒ€μž…μ— 따라 λ©”μ„œλ“œκ°€ μ‹€νŒ¨ν•˜κ±°λ‚˜ μ„±κ³΅ν•˜κ²Œ λœλ‹€.
  • μ„Έ 번째 방법은 flyBird λ©”μ„œλ“œλ₯Ό μˆ˜μ •ν•΄μ„œ 인자둜 μ „λ‹¬λœ bird의 νƒ€μž…μ΄ Penguin이 아닐 κ²½μš°μ—λ§Œ fly λ©”μ‹œμ§€λ₯Ό μ „μ†‘ν•˜λ„λ‘ ν•œλ‹€.
public void flyBird(Bird bird) {
// 인자둜 μ „λ‹¬λœ λͺ¨λ“  birdκ°€ Penguin의 μΈμŠ€ν„΄μŠ€κ°€ 아닐 κ²½μš°μ—λ§Œ
// fly() λ©”μ‹œμ§€λ₯Ό μ „μ†‘ν•œλ‹€.
if (!(bird instanceof Penguin)) {
bird.fly();
}
}
  • ν•˜μ§€λ§Œ 이 κ²½μš°μ—λŠ” λ§Œμ•½ Penguin 이외에 λ‚  수 μ—†λŠ” 또 λ‹€λ₯Έ μƒˆκ°€ 상속 계측에 μΆ”κ°€λœλ‹€λ©΄ μƒˆλ‘œμš΄ νƒ€μž…μ„ μ²΄ν¬ν•˜λŠ” μ½”λ“œλ₯Ό μΆ”κ°€ν•΄μ•Ό ν•œλ‹€. 개방-폐쇄 원칙을 μœ„λ°˜ν•œλ‹€.

🎈 ν΄λΌμ΄μ–ΈνŠΈμ˜ κΈ°λŒ€μ— 따라 계측 λΆ„λ¦¬ν•˜κΈ°β€‹

  • 문제λ₯Ό ν•΄κ²°ν•  수 μžˆλŠ” 방법은 ν΄λΌμ΄μ–ΈνŠΈμ˜ κΈ°λŒ€μ— 맞게 상속 계측을 λΆ„λ¦¬ν•˜λŠ” 것이닀.
  • λ‚  수 μžˆλŠ” μƒˆμ™€ λ‚  수 μ—†λŠ” μƒˆλ₯Ό λͺ…ν™•ν•˜κ²Œ ꡬ뢄할 수 있게 상속 계측을 λΆ„λ¦¬ν•˜λ©΄ μ„œλ‘œ λ‹€λ₯Έ μš”κ΅¬μ‚¬ν•­μ„ 가진 ν΄λΌμ΄μ–ΈνŠΈλ₯Ό λ§Œμ‘±μ‹œν‚¬ 수 μžˆλ‹€.
public class Bird {
// ...
}

public class FlyingBird extends Bird {
public void fly() {...}
}

public class Penguin extends Bird {
// ...
}
  • 이제 flyBird λ©”μ„œλ“œλŠ” FlyingBird νƒ€μž…μ„ μ΄μš©ν•΄ λ‚  수 μžˆλŠ” μƒˆλ§Œ 인자둜 전달돼야 ν•œλ‹€λŠ” 사싀을 μ½”λ“œμ— λͺ…μ‹œν•  수 μžˆλ‹€.
public void flyBird(FlyingBird bird) {
bird.fly();
}
  • 이 문제λ₯Ό ν•΄κ²°ν•˜λŠ” λ‹€λ₯Έ 방법은 ν΄λΌμ΄μ–ΈνŠΈμ— 따라 μΈν„°νŽ˜μ΄μŠ€λ₯Ό λΆ„λ¦¬ν•˜λŠ” 것이닀. μΈν„°νŽ˜μ΄μŠ€λŠ” ν΄λΌμ΄μ–ΈνŠΈκ°€ κΈ°λŒ€ν•˜λŠ” 바에 따라 뢄리돼야 ν•œλ‹€. ν΄λΌμ΄μ–ΈνŠΈμ— 따라 μΈν„°νŽ˜μ΄μŠ€λ₯Ό λΆ„λ¦¬ν•˜λ©΄ 변경에 λŒ€ν•œ 영ν–₯을 더 μ„Έλ°€ν•˜κ²Œ μ œμ–΄ν•  수 있게 λœλ‹€.
  • μΈν„°νŽ˜μ΄μŠ€λ₯Ό ν΄λΌμ΄μ–ΈνŠΈμ˜ κΈ°λŒ€μ— 따라 λΆ„λ¦¬ν•¨μœΌλ‘œμ¨ 변경에 μ˜ν•΄ 영ν–₯을 μ œμ–΄ν•˜λŠ” 섀계 원칙을 μΈν„°νŽ˜μ΄μŠ€ 뢄리 원칙(ISP)이라고 λΆ€λ₯Έλ‹€.

🎈 μ„œλΈŒν΄λž˜μ‹±κ³Ό μ„œλΈŒνƒ€μ΄ν•‘β€‹

  • μƒμ†μ˜ 두 가지 λͺ©μ μ€ μ½”λ“œ μž¬μ‚¬μš”μ„ μœ„ν•΄μ„œκ³ , λ‹€λ₯Έ ν•˜λ‚˜λŠ” νƒ€μž… 계측을 κ΅¬μ„±ν•˜κΈ° μœ„ν•΄μ„œλ‹€.
  • 상속을 μ‚¬μš©ν•˜λŠ” 두 가지 λͺ©μ μ— νŠΉλ³„ν•œ 이름을 λΆ™μ˜€λŠ”λ° μ„œλΈŒν΄λž˜μ‹±κ³Ό μ„œλΈŒνƒ€μ΄ν•‘μ΄ 그것이닀.

μ„œλΈŒν΄λž˜μ‹±(subclassing)

  • λ‹€λ₯Έ 클래슀의 μ½”λ“œλ₯Ό μž¬μ‚¬μš©ν•  λͺ©μ μœΌλ‘œ 상속을 μ‚¬μš©ν•˜λŠ” 경우λ₯Ό 가리킨닀. μžμ‹ ν΄λž˜μŠ€μ™€ λΆ€λͺ¨ 클래슀의 해동이 ν˜Έν™˜λ˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— μžμ‹ 클래슀의 μΈμŠ€ν„΄μŠ€κ°€ λΆ€λͺ¨ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό λŒ€μ²΄ν•  수 μ—†λ‹€.
  • μ„œλΈŒν΄λž˜μ‹±μ„ κ΅¬ν˜„ μƒμ†λ˜λŠ” 클래슀 상속이라고 λΆ€λ₯Έλ‹€.

μ„œλΈŒνƒ€μ΄ν•‘(subtyping)

  • νƒ€μž… 계측을 κ΅¬μ„±ν•˜κΈ° μœ„ν•΄ 상속을 μ‚¬μš©ν•˜λŠ” 경우λ₯Ό 가리킨닀. μžμ‹ ν΄λž˜μŠ€μ™€ λΆ€λͺ¨ 클래슀의 행동이 ν˜Έν™˜λ˜κΈ° λ•Œλ¬Έμ— μžμ‹ 클래슀의 μΈμŠ€ν„΄μŠ€κ°€ λΆ€λͺ¨ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό λŒ€μ²΄ν•  수 μžˆλ‹€. μ΄λ•Œ λΆ€λͺ¨ ν΄λž˜μŠ€λŠ” μžμ‹ 클래슀의 μŠˆνΌνƒ€μž…μ΄ 되고 μžμ‹ ν΄λž˜μŠ€λŠ” λΆ€λͺ¨ 클래슀의 μ„œλΈŒνƒ€μž…μ΄ λœλ‹€.
  • μ„œλΈŒνƒ€μ΄ν•‘μ„ μΈν„°νŽ˜μ΄μŠ€ 상속이라고 λΆ€λ₯΄κΈ°λ„ ν•œλ‹€.
  • μ„œλΈŒν΄λž˜μ‹±κ³Ό μ„œλΈŒνƒ€μ΄ν•‘μ„ λ‚˜λˆ„λŠ” 기쀀은 상속을 μ‚¬μš©ν•˜λŠ” λͺ©μ μ΄λ‹€.
  • μ„œλΈŒνƒ€μ΄ν•‘ 관계가 μœ μ§€λ˜κΈ° μœ„ν•΄μ„œλŠ” μ„œλΈŒνƒ€μž…μ΄ μŠˆνΌνƒ€μž…μ΄ ν•˜λŠ” λͺ¨λ“  행동을 λ™μΌν•˜κ²Œ ν•  수 μžˆμ–΄μ•Ό ν•œλ‹€. 즉, μ–΄λ–€ νƒ€μž…μ΄ λ‹€λ₯Έ νƒ€μž…μ˜ μ„œλΈŒνƒ€μž…μ΄ 되기 μœ„ν•΄μ„œλŠ” 행동 ν˜Έν™˜μ„±μ„ λ§Œμ‘±μ‹œμΌœμ•Ό ν•œλ‹€.
  • μžμ‹ ν΄λž˜μŠ€μ™€ λΆ€λͺ¨ 클래슀 μ‚¬μ΄μ˜ 행동 ν˜Έν™˜μ„±μ€ λΆ€λͺ¨ ν΄λž˜μŠ€μ— λŒ€ν•œ μžμ‹ 클래슀의 λŒ€μ²΄ κ°€λŠ₯성을 ν¬ν•¨ν•œλ‹€.

πŸ“š λ¦¬μŠ€μ½”ν”„ μΉ˜ν™˜ 원칙​

  • λ¦¬μŠ€μ½”ν”„ μΉ˜ν™˜ 원칙(LSP)λŠ” μ„œλΈŒνƒ€μž…μ€ κ·Έκ²ƒμ˜ 기반 νƒ€μž…μ— λŒ€ν•΄ λŒ€μ²΄ κ°€λŠ₯ν•΄μ•Όν•œλ‹€λŠ” κ²ƒμœΌλ‘œ ν΄λΌμ΄μ–ΈνŠΈκ°€ 차이점을 μΈμ‹ν•˜μ§€ λͺ»ν•œ 채 기반 클래슀의 μΈν„°νŽ˜μ΄μŠ€λ₯Ό 톡해 μ„œλΈŒν΄λž˜μŠ€λ₯Ό μ‚¬μš©ν•  수 μžˆμ–΄μ•Ό ν•œλ‹€.
  • λ¦¬μŠ€μ½”ν”„ μΉ˜ν™˜ 원칙에 λ”°λ₯΄λ©΄ μžμ‹ ν΄λž˜μŠ€κ°€ λΆ€λͺ¨ ν΄λž˜μŠ€μ™€ 행동 ν˜Έν™˜μ„±μ„ μœ μ§€ν•¨μœΌλ‘œμ¨ λΆ€λͺ¨ 클래슀λ₯Ό λŒ€μ²΄ν•  수 μžˆλ„λ‘ κ΅¬ν˜„λœ 상속 κ΄€κ³„λ§Œμ„ μ„œλΈŒνƒ€μ΄ν•‘μ΄λΌκ³  λΆˆλŸ¬μ•Ό ν•œλ‹€.
  • 이번 μ˜ˆμ œλŠ” μ •μ‚¬κ°ν˜•μ€ μ§μ‚¬κ°ν˜•μ΄λ‹€λΌλŠ” 이야기이닀. ν•˜μ§€λ§Œ μ •μ‚¬κ°ν˜•μ€ μ§μ‚¬κ°ν˜•μ΄ 아닐 수 μžˆλ‹€. 이 상속 κ΄€κ³„λŠ” λ¦¬μŠ€μ½”ν”„ μΉ˜ν™˜ 원칙을 μœ„λ°˜ν•˜λŠ” 고전적인 사둀 쀑 ν•˜λ‚˜λ‹€.
  • μ•„λž˜λŠ” μ§μ‚¬κ°ν˜•μ„ κ΅¬ν˜„ν•œ Rectangle이닀.
public class Rectangle {
private int x, y, width, height;

public Rectangle(int x, int y, int width, int height) {
this.x = x; // μ™Όμͺ½ 상단 λͺ¨μ„œλ¦¬ μœ„μΉ˜ (x, y)
this.y = y;
this.width = width; // λ„ˆλΉ„
this.height = height; // 높이
}

public int getWidth() {
return width;
}

public void setWidth(int width) {
this.width = width;
}

public int getHeight() {
return height;
}

public void setHeight(int height) {
this.height = height;
}

public int getArea() {
return width * height;
}
}
  • μ •μ‚¬κ°ν˜•μ€ μ§μ‚¬κ°ν˜•μ˜ νŠΉμˆ˜ν•œ 경우이고 μ§μ‚¬κ°ν˜•μ€ μ •μ‚¬κ°ν˜•μ˜ 일반적인 경우이기 λ•Œλ¬Έμ— μ •μ‚¬κ°ν˜•κ³Ό μ§μ‚¬κ°ν˜•μ˜ 사이에 μ–΄νœ˜μ μœΌλ‘œ is-a관계가 μ„±λ¦½ν•œλ‹€.
  • μ •μ‚¬κ°ν˜•μ€ λ„ˆλΉ„μ™€ 높이가 동일해야 ν•œλ‹€.
public class Square extends Rectangle {
public Square(int x, int y, int size) {
super(x, y, size, size);
}

@Override
public void setWidth(int width) {
super.setWidth(width);
super.setHeight(width);
}

@Override
public void setHeight(int height) {
super.setWidth(height);
super.setHeight(height);
}
}
  • SquareλŠ” Rectangle의 μžμ‹ 클래슀이기 λ•Œλ¬Έμ— Rectangle이 μ‚¬μš©λ˜λŠ” λͺ¨λ“  κ³³μ—μ„œ Rectangle둜 μ—…μΊμŠ€νŒ…λ  수 μžˆλ‹€. λ¬Έμ œλŠ” Rectangleκ³Ό ν˜‘λ ₯ν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈλŠ” μ§μ‚¬κ°ν˜• λ„ˆλΉ„μ™€ 높이가 λ‹€λ₯΄λ‹€κ³  κ°€μ‘ν• λ•Œ λ°œμƒν•œλ‹€. λ”°λΌμ„œ μ•„λž˜ μ½”λ“œμ²˜λŸΌ μ§μ‚¬κ°ν˜•μ˜ λ„ˆλΉ„μ™€ 높이λ₯Ό μ„œλ‘œ λ‹€λ₯΄κ²Œ μ„€μ •ν•˜λ„λ‘ ν”„λ‘œκ·Έλž˜λ°ν•  것이닀.
public void resize(Rectangle rectangle, int width, int height) {
rectangle.setWidth(width);
rectangle.setHeight(height);
assert rectangle.getWidth() === width && rectangle.getHeight() === height;
}
  • κ·ΈλŸ¬λ‚˜ resize λ©”μ„œλ“œμ˜ 인자둜 Squareλ₯Ό μ „λ‹¬ν•œλ‹€κ³  가정해보면, 더 λ‚˜μ€‘μ— μ„€μ •λœ height의 κ°’μœΌλ‘œ κ°™μ•„μ§€κ²Œ λœλ‹€. λ”°λΌμ„œ λ‹€μŒκ³Ό 같이 width와 height값을 λ‹€λ₯΄κ²Œ μ„€μ •ν•  경우 λ©”μ„œλ“œ 싀행에 μ‹€νŒ¨ν•˜κ³  말 것이닀.
Square square = new Square(10, 10, 10);
resize.(square, 50, 100);
  • resize λ©”μ„œλ“œμ˜ κ΄€μ γ„΄μ—μ„œ RectangleλŒ€μ‹  Squareλ₯Ό μ‚¬μš©ν•  수 μ—†κΈ° λ•Œλ¬Έμ— SquareλŠ” Rectangle이 μ•„λ‹ˆλ‹€. 두 ν΄λž˜μŠ€λŠ” κ΅¬ν˜„μ„ μž¬μ‚¬μš©ν•˜κ³  μžˆμ„ 뿐이기 λ•Œλ¬Έμ— λ¦¬μŠ€μ½”ν”„ μΉ˜ν™˜ 원칙을 μœ„λ°˜ν•œλ‹€. λ”°λΌμ„œ μ„œλΈŒνƒ€μ΄ν•‘ 관계가 μ•„λ‹ˆλΌ μ„œλΈŒν΄λž˜μ‹± 관계닀.

🎈 ν΄λΌμ΄μ–ΈνŠΈμ™€ λŒ€μ²΄ κ°€λŠ₯성​

  • ν΄λΌμ΄μ–ΈνŠΈ μž…μž₯μ—μ„œ μ •μ‚¬κ°ν˜•μ„ μΆ”μƒν™”ν•œ SquareλŠ” μ§μ‚¬κ°ν˜•μ„ μΆ”μƒν™”ν•œ Rectangleκ³Ό λ™μΌν•˜μ§€ μ•Šλ‹€.
  • λ¦¬μŠ€μ½”ν”„ μΉ˜ν™˜ 원칙은 μžμ‹ ν΄λž˜μŠ€κ°€ λΆ€λͺ¨ 클래슀λ₯Ό λŒ€μ²΄ν•˜κΈ° μœ„ν•΄μ„œλŠ” λΆ€λͺ¨ ν΄λž˜μŠ€μ— λŒ€ν•œ ν΄λΌμ΄μ–ΈνŠΈμ˜ 가정을 μ€€μˆ˜ν•΄μ•Ό ν•œλ‹€λŠ” 것을 κ°•μ‘°ν•œλ‹€.
  • λ¦¬μŠ€μ½”ν”„ μΉ˜ν™˜ 원칙은 상속 관계에 μžˆλŠ” 두 클래슀 μ‚¬μ΄μ˜ 관계λ₯Ό ν΄λΌμ΄μ–ΈνŠΈμ™€ λ–¨μ–΄νŠΈλ € 놓고 νŒλ‹¨ν•˜μ§€ 말아야 ν•œλ‹€. 상속 κ΄€κ³„λŠ” ν΄λΌμ΄μ–ΈνŠΈμ˜ κ΄€μ μ—μ„œ μžμ‹ ν΄λž˜μŠ€μ™€ λΆ€λͺ¨ 클래슀λ₯Ό λŒ€μ²΄ν•  수 μžˆμ„ λ•Œλ§Œ μ˜¬λ°”λ₯΄λ‹€.
  • λŒ€μ²΄ κ°€λŠ₯성을 κ²°μ •ν•˜λŠ” 것은 ν΄λΌμ΄μ–ΈνŠΈλ‹€.

🎈 is-a 관계 λ‹€μ‹œ μ‚΄νŽ΄λ³΄κΈ°β€‹

  • ν΄λΌμ΄μ–ΈνŠΈ κ΄€μ μ—μ„œ μžμ‹ 클래슀의 행동이 λΆ€λͺ¨ 클래슀의 행동과 ν˜Έν™˜λ˜μ§€ μ•Šκ³  그둜 인해 λŒ€μ²΄κ°€ λΆˆκ°€λŠ₯ν•˜λ‹€λ©΄ μ–΄νœ˜μ μœΌλ‘œ is-a라고 말할 수 μžˆλ‹€κ³  ν•˜λ”λΌλ„ κ·Έ 관계λ₯Ό is-a 관계라고 ν•  수 μ—†λ‹€.
  • is-aλŠ” ν΄λΌμ΄μ–ΈνŠΈ κ΄€μ μ—μ„œ is-a일 λ•Œλ§Œ 참이닀. ν΄λΌμ΄μ–ΈνŠΈκ°€ 이 λ‘˜μ„ λ™μΌν•˜κ²Œ μ·¨κΈ‰ν•  수 μžˆμ„ λ•Œλ§Œ κ·Έλ ‡λ‹€. (ν΄λΌμ΄μ–ΈνŠΈ μž…μž₯μ—μ„œ μ •μ‚¬κ°ν˜•μ€ μ§μ‚¬κ°ν˜•μΈκ°€? ν΄λΌμ΄μ–ΈνŠΈ μž…μž₯μ—μ„œ νŽ­κ·„μ€ μƒˆμΈκ°€?)
  • is-a κ΄€κ³„λŠ” 객체지ν–₯μ—μ„œ μ€‘μš”ν•œ 것은 객체의 속성이 μ•„λ‹ˆλΌ 객체의 ν–‰λ™μ΄λΌλŠ” 점을 κ°•μ‘°ν•œλ‹€.
  • μŠˆνΌνƒ€μž…κ³Ό μ„œλΈŒνƒ€μž…μ΄ ν΄λΌμ΄μ–ΈνŠΈ μž…μž₯μ—μ„œ 행동이 ν˜Έν™˜λœλ‹€λ©΄ 두 νƒ€μž…μ„ is-a둜 μ—°κ²°ν•΄ λ¬Έμž₯을 λ§Œλ“€μ–΄λ„ μ–΄μƒ‰ν•˜μ§€ μ•Šμ€ λ‹¨μ–΄λ‘œ νƒ€μž…μ˜ 이름을 μ •ν•˜λΌλŠ” 것이닀.
  • 결둠적으둜 상속이 μ„œλΈŒνƒ€μ΄ν•‘μ„ μœ„ν•΄ μ‚¬μš©λ  κ²½μš°μ—λ§Œ is-a관계닀.

🎈 λ¦¬μŠ€μ½”ν”„ μΉ˜ν™˜ 원칙은 μœ μ—°ν•œ μ„€κ³„μ˜ κΈ°λ°˜μ΄λ‹€.​

  • μƒˆλ‘œμš΄ μžμ‹ 클래슀λ₯Ό μΆ”κ°€ν•˜λ”λΌλ„ ν΄λΌμ΄μ–ΈνŠΈ μž…μž₯μ—μ„œ λ™μΌν•˜κ²Œ ν–‰λ™ν•˜κΈ°λ§Œ ν•œλ‹€λ©΄ ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μˆ˜μ •ν•˜μ§€ μ•Šκ³ λ„ 상속 계측을 ν™•μž₯ν•  수 μžˆλ‹€.
  • λ¦¬μŠ€μ½”ν”„ μΉ˜ν™˜ 원칙을 λ”°λ₯΄λŠ” μ„€κ³„λŠ” μœ μ—°ν• λΏλ§Œ μ•„λ‹ˆλΌ ν™•μž₯성이 λ†’λ‹€.
  • λ¦¬μŠ€μ½”ν”„ μΉ˜ν™˜ 원칙은 개방-폐쇄 원칙을 λ§Œμ‘±ν•˜λŠ” 섀계λ₯Ό μœ„ν•œ μ „μ œ 쑰건이닀.

🎈 νƒ€μž… 계측과 λ¦¬μŠ€μ½”ν”„ μΉ˜ν™˜ 원칙​

  • κ΅¬ν˜„ 방법과 λ¬΄κ΄€ν•˜κ²Œ ν΄λΌμ΄μ–ΈνŠΈμ˜ κ΄€μ μ—μ„œ μŠˆνΌνƒ€μž…μ— λŒ€ν•΄ κΈ°λŒ€ν•˜λŠ” λͺ¨λ“  것이 μ„œλΈŒνƒ€μž…μ—κ²Œλ„ μ μš©λΌμ•Ό ν•œλ‹€λŠ” 것이닀.

πŸ“š 계약에 μ˜ν•œ 섀계와 μ„œλΈŒνƒ€μ΄ν•‘β€‹

  • ν΄λΌμ΄μ–ΈνŠΈμ™€ μ„œλ²„ μ‚¬μ΄μ˜ ν˜‘λ ₯을 μ˜λ¬΄μ™€ 이읡으둜 κ΅¬μ„±λœ κ³„μ•½μ˜ κ΄€μ μ—μ„œ ν‘œν˜„ν•˜λŠ” 것을 계약에 μ˜ν•œ 섀계(DBC)라고 λΆ€λ₯Έλ‹€.
  • 계약에 μ˜ν•œ μ„€κ³„λŠ” ν΄λΌμ΄μ–ΈνŠΈκ°€ μ •μƒμ μœΌλ‘œ λ©”μ„œλ“œλ₯Ό μ‹€ν–‰ν•˜κΈ° μœ„ν•΄ λ§Œμ‘±μ‹œμΌœμ•Ό ν•˜λŠ” 사전쑰건과 λ©”μ„œλ“œκ°€ μ‹€ν–‰λœ 후에 μ„œλ²„κ°€ ν΄λΌμ΄μ–ΈνŠΈμ—κ²Œ 보μž₯ν•΄μ•Όν•˜λŠ” 사후쑰건, λ©”μ„œλ“œ μ‹€ν–‰ μ „κ³Ό μ‹€ν–‰ 후에 μΈμŠ€ν„΄μŠ€κ°€ λ§Œμ‘±μ‹œμΌœμ•Ό ν•˜λŠ” 클래슀 λΆˆλ³€μ‹μ˜ μ„Έ 가지 μš”μ†Œλ‘œ κ΅¬μ„±λœλ‹€.
  • 계약에 μ˜ν•œ 섀계λ₯Ό μ‚¬μš©ν•˜λ©΄ λ¦¬μŠ€μ½”ν”„ μΉ˜ν™˜ 원칙이 κ°•μ œν•˜λŠ” 쑰건을 κ³„μ•½μ˜ κ°œλ…μ„ μ΄μš©ν•΄ μ’€ 더 λͺ…ν™•ν•˜κ²Œ μ„€λͺ…ν•  수 μžˆλ‹€.

μ„œλΈŒνƒ€μž…μ΄ λ¦¬μŠ€μ½”ν”„ μΉ˜ν™˜ 원칙을 λ§Œμ‘±μ‹œν‚€κΈ° μœ„ν•΄μ„œλŠ” ν΄λΌμ΄μ–ΈνŠΈμ™€ μŠˆνΌνƒ€μž… 간에 체결된 계약을 μ€€μˆ˜ν•΄μ•Ό ν•œλ‹€.

  • 계약에 μ˜ν•œ 섀계에 λ”°λ₯΄λ©΄ ν˜‘λ ₯ν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈμ™€ μŠˆνΌνƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€ μ‚¬μ΄μ—λŠ” μ–΄λ–€ 계약이 λ§Ίμ–΄μ Έ μžˆλ‹€. ν΄λΌμ΄μ–ΈνŠΈμ™€ μŠˆνΌνƒ€μž…μ€ 이 계약을 μ€€μˆ˜ν•  λ•Œλ§Œ μ •μƒμ μœΌλ‘œ ν˜‘λ ₯ν•œλ‹€. ν΄λΌμ΄μ–ΈνŠΈ μž…μž₯μ—μ„œ μ„œλΈŒνƒ€μž…μ€ μŠˆνΌνƒ€μž…μ˜ ν•œ μ’…λ₯˜μ—¬μ•Ό ν•˜λŠ” 것이닀.

예제 μƒλž΅.

🎈 μ„œλΈŒνƒ€μž…κ³Ό 계약​

  • κ³„μ•½μ˜ κ΄€μ μ—μ„œ 상속이 μ΄ˆλž˜ν•˜λŠ” κ°€μž₯ 큰 λ¬Έμ œλŠ” μžμ‹ ν΄λž˜μŠ€κ°€ λΆ€λͺ¨ 클래슀의 λ©”μ„œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ”©ν•  수 μžˆλ‹€λŠ” 것이닀.
  • 예λ₯Ό λ“€μ–΄μ„œ DiscountPolicyλ₯Ό μƒμ†λ°›λŠ” BrokenDiscountPolicy ν΄λž˜μŠ€λŠ” calculateDiscountAmount λ©”μ„œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ”©ν•œ ν›„ 여기에 μƒˆλ‘œμš΄ 사전쑰건을 μΆ”κ°€ν•œλ‹€. 이 μƒˆλ‘œμš΄ 사전쑰건은 μ’…λ£Œ μ‹œκ°„μ΄ μžμ •μ„ λ„˜λŠ” μ˜ν™”λ₯Ό μ˜ˆλ§€ν•  수 μ—†λ‹€λŠ” 것이닀. λ”°λΌμ„œ DiscountPolicy보닀 더 κ°•ν™”λœ 사전쑰건을 μ •μ˜ν•œλ‹€.
public class BrokenDiscountPolicy extends DiscountPolicy {
public BrokenDiscountPolicy(DiscountCondition ... conditions) {
super(conditions);
}

@Override
public Money calculateDiscountAmount(Screening screening) {
checkPrecondition(screening); // 기쑴의 사전쑰건
checkStrongPrecondition(screening); // 더 κ°•λ ₯ν•œ 사전쑰건

Money amount = screening.getMovieFee();;
checkPostcondition(amount); // 기쑴의 사후쑰건
return amount;
}

// ...
}
  • BrokenDiscountPolicy ν΄λž˜μŠ€κ°€ DiscountPolicy 클래슀의 μžμ‹ 클래슀이기 λ•Œλ¬Έμ— μ»΄νŒŒμΌλŸ¬λŠ” μ•„λ¬΄λŸ° μ œμ•½ 없이 μ—…μΊμŠ€νŒ…μ„ ν—ˆμš©ν•œλ‹€. λ¬Έμ œλŠ” MovieλŠ” 였직 DiscountPolicy의 μ‚¬μ „μ‘°κ±΄λ§Œ μ•Œκ³  μžˆλ‹€λŠ” 점이닀. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— BrokenDiscountPolicy의 μΆ”κ°€ν•œ 사전쑰건은 이λ₯Ό ν—ˆμš©ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— ν˜‘λ ₯은 μ‹€νŒ¨ν•˜κ³  λ§Œλ‹€. λ‹€μ‹œλ§ν•΄μ„œ ν΄λΌμ΄μ–ΈνŠΈ κ΄€μ μ—μ„œ DiscountPolicyλ₯Ό λŒ€μ²΄ν•  수 μ—†κΈ° λ•Œλ¬Έμ— μ„œλΈŒνƒ€μž…μ΄ μ•„λ‹ˆλ‹€.
  • λ”°λΌμ„œ μžμ‹ ν΄λž˜μŠ€κ°€ λΆ€λͺ¨ 클래슀의 μ„œλΈŒνƒ€μž…μ΄ 되기 μœ„ν•΄μ„œλŠ” λ‹€μŒ 쑰건을 λ§Œμ‘±μ‹œμΌœμ•Ό ν•œλ‹€.

πŸ“Œ μ„œλΈŒνƒ€μž…μ— 더 κ°•λ ₯ν•œ 사전쑰건을 μ •μ˜ν•  수 μ—†λ‹€.

  • κ·Έ λ°˜λŒ€λ‘œ 사전쑰건을 μ œκ±°ν•΄μ„œ μ•½ν™”μ‹œν‚¨λ‹€λ©΄ μ–΄λ–»κ²Œ 될까?
public class BrokenDiscountPolicy extends DiscountPolicy {
// ...
@Override
public Money calculateDiscountAmount(Screening screening) {
// checkPrecondition(screening); // 기쑴의 사전쑰건 제거

Money amount = screening.getMovieFee();;
checkPostcondition(amount); // 기쑴의 사후쑰건
return amount;
}
// ...
}
  • BrokenDiscountPolicyλŠ” Screening에 λŒ€ν•œ 사전쑰건을 μ²΄ν¬ν•˜μ§€ μ•Šμ•˜μ§€λ§Œ MovieλŠ” DiscountPolicyκ°€ μ •μ˜ν•œ 사전쑰건을 λ§Œμ‘±μ‹œν‚€κΈ° μœ„ν•΄ null이 μ•„λ‹ˆλ©° ν˜„μž¬ μ‹œκ°„ 이후에 μ‹œμž‘ν•˜λŠ” Screening을 μ „λ‹¬ν•˜λŠ” 것을 보μž₯ν•˜κ³  μžˆλ‹€. λ”°λΌμ„œ 이 κ²½μš°μ—λŠ” μ•„λ¬΄λŸ° λ¬Έμ œλ„ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.

πŸ“Œ μ„œλΈŒνƒ€μž…μ— μŠˆνΌνƒ€μž…κ³Ό κ°™κ±°λ‚˜ 더 μ•½ν•œ 사전쑰건을 μ •μ˜ν•  수 μžˆλ‹€.

  • λ§Œμ•½ 사후쑰건을 κ°•ν™”ν•œλ‹€λ©΄ μ–΄λ–»κ²Œ 될까?
public class BrokenDiscountPolicy extends DiscountPolicy {
// ...
@Override
public Money calculateDiscountAmount(Screening screening) {
checkPrecondition(screening); // 기쑴의 사전쑰건

Money amount = screening.getMovieFee();;
checkPostcondition(amount); // 기쑴의 사후쑰건
checkStrongerPostcondition(amount); // 더 κ°•λ ₯ν•œ 사후쑰건
return amount;
}
// ...
}
  • MovieλŠ” DiscountPolicy의 μ‚¬ν›„μ‘°κ±΄λ§Œ μ•Œκ³  μžˆλ‹€. MovieλŠ” μ΅œμ†Œν•œ 0보닀 큰 κΈˆμ•‘μ„ λ°˜ν™˜ν•˜κΈ°λ§Œ ν•˜λ©΄ ν˜‘λ ₯이 μ •μƒμ μœΌλ‘œ μˆ˜ν–‰λλ‹€κ³  κ°€μ •ν•œλ‹€. λ”°λΌμ„œ BrokenDiscountPolicyκ°€ 1000원 μ΄μƒμ˜ κΈˆμ•‘μ„ λ°˜ν™˜ν•˜λŠ” 것은 계약을 μœ„λ°˜ν•˜μ§€ μ•ŠλŠ”λ‹€. λ”°λΌμ„œ λ‹€μŒκ³Ό 같은 사싀을 μ•Œ 수 μžˆλ‹€.

πŸ“Œ μ„œλΈŒνƒ€μž…μ— μŠˆνΌνƒ€μž…κ³Ό κ°™κ±°λ‚˜ 더 κ°•ν•œ 사후쑰건을 μ •μ˜ν•  수 μžˆλ‹€.

  • 사후쑰건을 μ•½ν•˜κ²Œ μ •μ˜ν•˜λ©΄ μ–΄λ–»κ²Œ 될까?
public class BrokenDiscountPolicy extends DiscountPolicy {
// ...
@Override
public Money calculateDiscountAmount(Screening screening) {
checkPrecondition(screening); // 기쑴의 사전쑰건

Money amount = screening.getMovieFee();;
// checkPostcondition(amount); // 기쑴의 사후쑰건 제거
checkWeakerPostcondition(amount); // 더 μ•½ν•œ 사후쑰건
return amount;
}
// ...
}
  • 이 κ²½μš°μ—λŠ” μ›ν•˜μ§€ μ•Šμ•˜λ˜ 결과둜 이어지고 λ§Œλ‹€.

πŸ“Œ μ„œλΈŒνƒ€μž…μ— 더 μ•½ν•œ 사후쑰건을 μ •μ˜ν•  수 μ—†λ‹€.

  • 계약에 μ˜ν•œ μ„€κ³„λŠ” ν΄λΌμ΄μ–ΈνŠΈ κ΄€μ μ—μ„œ λŒ€μ²΄ κ°€λŠ₯성을 κ³„μ•½μœΌλ‘œ μ„€λͺ…ν•  수 μžˆλ‹€λŠ” 사싀을 잘 보여쀀닀. λ”°λΌμ„œ μ„œλΈŒνƒ€μ΄ν•‘μ„ μœ„ν•΄ 상속을 μ‚¬μš©ν•˜κ³  μžˆλ‹€λ©΄ λΆ€λͺ¨ ν΄λž˜μŠ€κ°€ ν΄λΌμ΄μ–ΈνŠΈμ™€ λ§Ίκ³  μžˆλŠ” 계약에 κ΄€ν•΄ 깊이 있게 κ³ λ―Όν•΄μ•Ό ν•œλ‹€.