Item 19. Inheritance

상속을 κ³ λ €ν•΄ μ„€κ³„ν•˜κ³  λ¬Έμ„œν™”ν•˜λΌ. κ·ΈλŸ¬μ§€ μ•Šμ•˜λ‹€λ©΄ 상속을 κΈˆμ§€ν•˜λΌ

μƒμ†μ˜ μœ„ν—˜μ„±

μ•žμ˜ μ•„μ΄ν…œμ—μ„œ λ‹€λ€˜λ“―μ΄ 상속은 μ½”λ“œλ₯Ό μž¬μ‚¬μš©ν•˜κΈ° μœ„ν•΄ μœ μš©ν•œ λ„κ΅¬μ΄μ§€λ§Œ, 항상 μ΅œμ„ μ΄ μ•„λ‹ˆλ©°, 잘λͺ» μ‚¬μš©ν•˜κ²Œλ˜λ©΄ 였λ₯˜λ₯Ό λ‚΄κΈ° μ‰½κ²Œ λœλ‹€. λ•Œλ¬Έμ— 클래슀λ₯Ό 섀계할 λ•Œ 상속을 κ³ λ €ν•΄μ•Όν•˜κ³  각 λ©”μ„œλ“œλ§ˆλ‹€ μ–΄λ–€ μ‹μœΌλ‘œ λ™μž‘ν• μ§€ μƒμ„Έν•˜κ²Œ λ¬Έμ„œν™”ν•΄μ•Ό ν•œλ‹€. λ§Œμ•½ 상속을 ν•˜κΈ°μ— λΆ€μ μ ˆν•œ 클래슀라면 상속을 κΈˆμ§€ν•˜λŠ” 쑰치λ₯Ό μ·¨ν•΄μ•Ό ν•œλ‹€.

상속을 κ³ λ €ν•œ 섀계와 λ¬Έμ„œν™”

상속을 κ³ λ €ν•œ 섀계와 λ¬Έμ„œν™”λ₯Ό ν•˜κ³ μž ν•œλ‹€λ©΄ μ•„λž˜μ˜ 사항듀을 μ§€ν‚€λŠ” 것이 μ’‹λ‹€.

1. @implSpec을 ν†΅ν•œ λ¬Έμ„œν™”

주석에 @implSpec νƒœκ·Έλ₯Ό μΆ”κ°€ν•˜μ—¬ Implentation Requirements λ‚΄μš©μ„ λ¬Έμ„œν™”ν•˜μ—¬ ν΄λΌμ΄μ–ΈνŠΈμ—κ²Œ 정보λ₯Ό μ œκ³΅ν•΄ 쀄 수 μžˆλ‹€.

/**
 * {@inheritDoc}
 *
 * @implSpec 이 κ΅¬ν˜„μ€ λ‹€μŒκ³Ό κ°™λ‹€.
 * {@code
 *  return 1;
 * }
 */

2. protectedλ₯Ό μ΄μš©ν•œ λ©”μ„œλ“œ 곡개

클래슀의 λ‚΄λΆ€ λ™μž‘ κ³Όμ • 쀑간에 끼어듀 수 μžˆλŠ” 훅을 잘 μ„ λ³„ν•˜μ—¬ protected λ©”μ„œλ“œ ν˜•νƒœλ‘œ κ³΅κ°œν•˜μ—¬ 큰 어렀움 없이 효율적인 ν•˜μœ„ 클래슀λ₯Ό λ§Œλ“€ 수 μžˆλ„λ‘ ν•  수 μžˆλ‹€. μ‹€μ œλ‘œ java.util.AbstractList의 removeRange λ©”μ„œλ“œλŠ” protected둜 μ„ μ–Έλ˜μ–΄ μžˆλ‹€. List κ΅¬ν˜„μ²΄λ₯Ό μ‚¬μš©ν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈλŠ” ν•΄λ‹Ή λ©”μ„œλ“œμ˜ 쑴재λ₯Ό λͺ¨λ₯΄μ§€λ§Œ, AbstractListλ₯Ό μƒμ†ν•œ ν•˜μœ„ ν΄λž˜μŠ€λŠ” ν•΄λ‹Ή λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ 효율적으둜 clear λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•  수 있게 λœλ‹€.

protect의 곡개 μ—¬λΆ€λŠ” μ •ν™•νžˆ 정해진 것은 μ—†μœΌλ©°, ν•˜μœ„ 클래슀λ₯Ό λ§Œλ“€μ–΄λ³΄κ³  ν…ŒμŠ€νŠΈν•΄λ³΄λ©΄μ„œ μ μ ˆν•œμ§€ νŒλ‹¨ν•΄μ•Ό ν•œλ‹€. ν•˜μ§€λ§Œ λ§Žμ€ λ©”μ„œλ“œλ₯Ό λ…ΈμΆœν•˜λ©΄ μΊ‘μŠν™”κ°€ μ–΄λ €μ›Œμ§€κ³ , 적게 λ…ΈμΆœν•˜λ©΄ ν•˜μœ„ 클래슀λ₯Ό λ§Œλ“€κΈ° μ–΄λ €μ›Œμ§„λ‹€λŠ” 점을 λͺ…심해야 ν•œλ‹€.

3. μƒμ†μš© 클래슀의 μƒμ„±μž

μƒμ†μš© 클래슀의 μƒμ„±μžλŠ” 직/κ°„μ ‘μ μœΌλ‘œ μž¬μ •μ˜ κ°€λŠ₯ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•΄μ„œλŠ” μ•ˆλœλ‹€. μžμ„Έν•œ μ˜ˆμ‹œ 및 μ΄μœ λŠ” μ•„λž˜μ˜ μ½”λ“œλ₯Ό μ°Έκ³ ν•˜μž.

import java.time.Instant;

class Super {

    public Super() {
        overrideMe(); // 3. overrideMe() 호좜
    }

    public void overrideMe() {
    }
}

// ν•˜μœ„ 클래슀
final class Sub extends Super {

    private final Instant instant;

    Sub() {
        super(); // 2. μƒμœ„ 클래슀의 μƒμ„±μž 호좜
        instant = Instant.now(); // 6. instant μ΄ˆκΈ°ν™”
    }

    // 4. μƒμœ„ ν΄λž˜μŠ€μ—μ„œ 호좜 λ°›μ•„ μ˜€λ²„λΌμ΄λ”© 된 λ©”μ„œλ“œ μ‹€ν–‰
    public void overrideMe() {
        System.out.println(instant); // 5. 아직 μ΄ˆκΈ°ν™”λ˜μ§€ μ•Šμ€ instant 좜λ ₯
    }
}

class Main {
    public static void main(String[] args) {
        Sub sub = new Sub(); // 1. μƒμ„±μž 호좜
        sub.overrideMe(); // 7. overrideMe() ν˜ΈμΆœν•˜μ—¬ μ •μƒμ μœΌλ‘œ instant 좜λ ₯
    }
}

μ˜ˆμ‹œ μ½”λ“œμ—μ„œλŠ” System.out.println이 null을 μ—λŸ¬ 없이 μ‹€ν–‰μ‹œν‚€μ§€λ§Œ, λ§Œμ•½ λ‹€λ₯Έ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•œλ‹€λ©΄ NullPointerException이 λ°œμƒν•˜κ²Œ 될 수 μžˆλ‹€. λ•Œλ¬Έμ— μƒμ„±μž λ‚΄λΆ€μ—μ„œλŠ” private, final, static 같은 μž¬μ •μ˜ λΆˆκ°€λŠ₯ν•œ λ©”μ„œλ“œλ§Œ ν˜ΈμΆœν•΄μ•Ό ν•œλ‹€.

4. Cloneable, Serializable μΈν„°νŽ˜μ΄μŠ€

Cloneableκ³Ό Serializable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ ν΄λž˜μŠ€λŠ” μƒμ†μš©μœΌλ‘œ μ„€κ³„ν•˜κΈ°μ— μ ν•©ν•˜μ§€ μ•ŠμœΌλ©°, 일반적으둜 ꢌμž₯ν•˜μ§€ μ•ŠλŠ”λ‹€. Cloneable은 clone λ©”μ„œλ“œλ₯Ό, Serializable은 readObject λ©”μ„œλ“œλ₯Ό 각각 κ΅¬ν˜„ν•΄μ•Ό ν•˜κΈ° λ•Œλ¬Έμ— ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œλŠ” 이λ₯Ό κ΅¬ν˜„ν•΄μ•Ό ν•˜κΈ° λ•Œλ¬Έμ— ν™•μž₯의 뢀담이 더 μ»€μ§€κ²Œ λœλ‹€.

cloneκ³Ό readObject λ©”μ„œλ“œλŠ” μƒμ„±μžμ™€ λΉ„μŠ·ν•œ 효과(μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€ 생성)λ₯Ό λ‚΄κΈ° λ•Œλ¬Έμ—, λ§Œμ•½ κ΅¬ν˜„ ν•΄μ•Όν•œλ‹€λ©΄ λ§ˆμ°¬κ°€μ§€λ‘œ 직/κ°„μ ‘μ μœΌλ‘œ μž¬μ •μ˜ κ°€λŠ₯ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•΄μ„œλŠ” μ•ˆλœλ‹€.

5. μƒμ†μš© 클래슀의 직렬화

Serializable을 κ΅¬ν˜„ν•œ μƒμ†μš© ν΄λž˜μŠ€κ°€ readResolve ν˜Ήμ€ writeReplace λ©”μ„œλ“œλ₯Ό μ„ μ–Έν•˜λŠ” 경우 protected둜 μ„ μ–Έν•΄μ•Ό ν•œλ‹€. (private으둜 μ„ μ–Έν•˜λ©΄ ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œλŠ” ν•΄λ‹Ή λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•  수 μ—†κ²Œ λœλ‹€.)

상속 κΈˆμ§€

μœ„μ—μ„œ λ³΄μ•˜λ“―μ΄ 상속 κ°€λŠ₯ν•œ 클래슀λ₯Ό μ„€κ³„ν•˜κΈ° μœ„ν•΄μ„  λ§Žμ€ λ…Έλ ₯이 ν•„μš”ν•˜κΈ° λ•Œλ¬Έμ— 상속을 κΈˆμ§€ν•˜λŠ” 것이 더 쒋을 수 μžˆλ‹€. 상속을 κΈˆμ§€ν•˜λŠ” 방법은 μ•„λž˜ 두 가지가 μžˆλ‹€.

  • 클래슀λ₯Ό final둜 μ„ μ–Έ

  • λͺ¨λ“  μƒμ„±μžλ₯Ό private ν˜Ήμ€ package-private으둜 μ„ μ–Έν•˜κ³ , public 정적 νŒ©ν„°λ¦¬λ₯Ό 제곡

ν˜„μ‹€μ μΈ λŒ€μ•ˆ

사싀 λ§Žμ€ κ°œλ°œμžλ“€μ΄ μ² μ €ν•œ 섀계 μ•ˆμ—μ„œ 개발 ν•  수 μ—†κΈ° λ•Œλ¬Έμ—, μœ„μ˜ 원칙을 μ§€ν‚€λŠ” 것은 ν˜„μ‹€μ μœΌλ‘œ μ–΄λ ΅λ‹€. λ•Œλ¬Έμ— μ™„λ²½ν•œ 섀계가 μ•„λ‹ˆλ”λΌλ„ 무쑰건 상속을 κΈˆμ§€ν•˜λŠ” 것이 μ•„λ‹ˆλΌ 클래슀 λ‚΄λΆ€μ—μ„œ μž¬μ •μ˜ κ°€λŠ₯ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ²Œ λ§Œλ“€κ³ , ν•΄λ‹Ή 사싀을 λ¬Έμ„œν™”ν•˜λŠ” μ •λ„λ§Œ ν•˜λ”λΌλ„ μ˜€λ™μž‘μ„ 방지할 수 μžˆλ‹€.

Last updated

Was this helpful?