ch7_상속

통합 문서입니다.


1. 상속과 다형성

상속과 다형성

학습 목표


1. 상속이란 무엇인가

상속은 기존 클래스의 상태/행위를 재사용해 새로운 클래스를 정의하는 방법이다.

class Animal { ... }
class Dog extends Animal { ... }

적절한 관계:

부적절한 관계:


2. 상속의 장점과 비용

장점:

  1. 공통 코드 재사용
  2. 상위 타입 추상화
  3. 다형성 기반 확장성

비용:

  1. 부모-자식 강결합
  2. 부모 변경이 자식에 파급
  3. 깊은 계층에서 이해/디버깅 어려움

3. 오버라이딩(Overriding)

자식 클래스가 부모 메소드를 재정의하는 기능이다.

class Animal {
    void sound() { System.out.println("..."); }
}
class Dog extends Animal {
    @Override
    void sound() { System.out.println("멍멍"); }
}

규칙:

  1. 메소드 시그니처 동일
  2. 접근 제어는 더 좁힐 수 없음
  3. 반환 타입은 공변 반환 허용 범위 내
  4. @Override를 반드시 붙여 컴파일 타임 검증 권장

4. 다형성과 동적 바인딩

Animal a = new Dog();
a.sound(); // Dog.sound()

컴파일 시 타입은 Animal, 실행 시 실제 객체는 Dog이므로
호출 메소드는 런타임에 결정된다(동적 디스패치).

상속과 다형성 디스패치

다형성 장점:


5. 업캐스팅/다운캐스팅

5.1 업캐스팅

Animal a = new Dog(); // 자동

자식을 부모로 다루는 것은 안전해 자동 변환된다.

5.2 다운캐스팅

Animal a = new Dog();
Dog d = (Dog) a; // 명시적

실제 객체 타입이 다르면 ClassCastException 발생.
필요 시 instanceof로 안전성 점검.


6. super의 역할

super는 부모 멤버/생성자 접근에 사용한다.

class Dog extends Animal {
    Dog(String name) {
        super(name); // 부모 생성자 호출
    }
}

부모 생성자 호출은 자식 생성자 첫 줄에서 수행되어야 한다.


7. 추상 클래스(Abstract Class)

추상 클래스는 공통 구현 + 강제 규약을 함께 제공할 수 있다.

abstract class Shape {
    abstract double area();
    void print() { System.out.println("shape"); }
}

특징:


8. 상속 vs 조합(Composition)

조합은 “다른 객체를 필드로 포함”해 기능을 조립하는 방식이다.

class Car {
    private Engine engine;
}

선택 기준:

실무에서는 조합이 더 유연한 경우가 많다.


9. 다형성 설계 패턴 예시

  1. 결제 수단별 처리
  2. 알림 채널(Email/SMS/Push)
  3. 파일 저장 전략(Local/S3)

공통 상위 타입(추상클래스/인터페이스)으로 의존하면
구현체 추가 시 기존 코드 수정이 최소화된다.


10. 실무에서 자주 하는 실수

  1. 상속 계층이 너무 깊어짐
  2. 부모 클래스에 과도한 책임 집중
  3. 다운캐스팅 남용
  4. 오버라이딩 없이 복붙으로 메소드 중복
  5. 단순 재사용 목적으로 잘못된 상속 관계 도입

11. 정리


2. 문제

문제

ch7 범위(상속/오버라이딩/다형성/추상클래스) 문제입니다.


A. 상속 기초

  1. Animal 부모 클래스와 Dog, Cat 자식 클래스를 작성하시오.
  2. name, age 공통 필드는 부모에 두고 자식에서 재사용하시오.
  3. 각 자식 클래스에 고유 메소드를 추가하시오.
  4. super(...)를 사용해 부모 생성자를 호출하시오.

B. 오버라이딩

  1. sound() 메소드를 자식별로 오버라이딩하시오.
  2. @Override를 제거했을 때 발생할 수 있는 문제를 설명하시오.
  3. 접근제어를 잘못 좁힐 때 컴파일 오류를 재현하시오.
  4. 부모 메소드와 자식 메소드를 모두 호출하는 코드를 작성하시오(super.sound()).

C. 다형성

  1. Animal[] 배열에 Dog, Cat, Bird를 담고 반복 호출하시오.
  2. 업캐스팅된 참조에서 공통 메소드만 호출 가능한 이유를 설명하시오.
  3. instanceof를 사용해 안전한 다운캐스팅을 구현하시오.
  4. 잘못된 다운캐스팅으로 ClassCastException을 재현하고 수정하시오.

D. 추상 클래스

  1. Shape 추상 클래스를 만들고 area() 추상 메소드를 선언하시오.
  2. Circle, Rectangle 자식 클래스를 구현하시오.
  3. Shape 타입 컬렉션으로 전체 넓이 합계를 계산하시오.
  4. 추상 클래스에 공통 구현 메소드(printInfo)를 추가하시오.

E. 설계 문제

  1. 결제 시스템을 상속 구조로 설계해보시오.
  2. 같은 요구사항을 조합(Composition) 구조로 다시 설계하시오.
  3. 두 설계의 장단점을 비교하시오.

F. 챌린지

  1. 게임 캐릭터 계층(Character, Warrior, Mage)을 설계하고 스킬 오버라이딩을 구현하시오.
  2. final 메소드/클래스를 적용해 확장을 제한해야 하는 케이스를 구현하시오.
  3. 리스코프 치환 원칙(LSP)을 깨는 예시를 만들고 개선하시오.

제출 체크리스트

  1. 상속 관계가 진짜 is-a인지 검토했는가?
  2. 다운캐스팅은 최소화하고 안전검사를 했는가?
  3. 공통 코드는 부모로, 개별 동작은 자식으로 분리했는가?
  4. 상속 대신 조합이 더 나은 지점을 판단했는가?