공공부하자개발 · 영어 학습 노트
자바
중급객체지향과 코어 라이브러리0/9 완료
  • 01상속, 다형성, 오버라이딩
  • 02추상 클래스 vs 인터페이스
  • 03예외 처리
  • 04java.lang 심화
  • 05컬렉션 프레임워크 딥다이브
  • 06메서드 활용 패턴 (중급)
  • 07Object 메서드와 비교
  • 08java.time 실무 날짜 계산
  • 09HTTP 와 JSON 기초
사이트 소개개인정보처리방침연락처
© 2026 공부하자
홈 › 중급 › 01 / 9

상속, 다형성, 오버라이딩

섹션 7진행 0 / 9
1왜 배우는가2핵심 원리3코드 예제4응용 변형 예제5자주 하는 실수 (Tip)6연습 문제7정리‹ 이전다음 ›

6. 연습 문제

문제 1: 도형 계층과 넓이 합계

Shape를 sealed 인터페이스로, Circle(double r), Rect(double w, double h)를 record로 정의하고, List<Shape>의 총 넓이를 switch 패턴 매칭으로 계산하는 totalArea 메서드를 작성하라. default 절 없이 작성해야 한다.

정답 보기
java
import java.util.List;

sealed interface Shape permits Circle, Rect {}
record Circle(double r) implements Shape {}
record Rect(double w, double h) implements Shape {}

public class Main {
    static double totalArea(List<Shape> shapes) {
        double sum = 0;
        for (Shape s : shapes) {
            sum += switch (s) {
                case Circle c -> Math.PI * c.r() * c.r();
                case Rect r   -> r.w() * r.h();
            };
        }
        return sum;
    }

    public static void main(String[] args) {
        System.out.printf("%.2f%n", totalArea(List.of(new Circle(1), new Rect(2, 3))));
        // 출력: 9.14
    }
}

문제 2: 계좌 계층과 오버라이딩 규칙

Account 클래스에 withdraw(long amount) 메서드가 있고 잔액 부족 시 IllegalStateException을 던진다. 이를 상속한 OverdraftAccount는 한도(limit)까지 마이너스 출금을 허용한다. super.withdraw를 활용하지 말고 규칙에 맞게 오버라이딩하라. 또한 toString을 오버라이딩해 [계좌명] 잔액: N원 형식으로 출력하라.

정답 보기
java
class Account {
    protected final String name;
    protected long balance;

    Account(String name, long balance) {
        this.name = name;
        this.balance = balance;
    }

    void withdraw(long amount) {
        if (amount > balance) throw new IllegalStateException("잔액 부족");
        balance -= amount;
    }

    @Override
    public String toString() { return "[" + name + "] 잔액: " + balance + "원"; }
}

class OverdraftAccount extends Account {
    private final long limit;

    OverdraftAccount(String name, long balance, long limit) {
        super(name, balance);
        this.limit = limit;
    }

    @Override
    void withdraw(long amount) {   // 접근 범위 동일(package), 예외 범위 확장 없음
        if (amount > balance + limit) throw new IllegalStateException("한도 초과");
        balance -= amount;
    }
}

public class Main {
    public static void main(String[] args) {
        Account a = new OverdraftAccount("마이너스통장", 10_000, 50_000);
        a.withdraw(30_000);          // 동적 바인딩 → OverdraftAccount.withdraw
        System.out.println(a);       // 출력: [마이너스통장] 잔액: -20000원
        try {
            a.withdraw(40_000);
        } catch (IllegalStateException e) {
            System.out.println(e.getMessage());   // 출력: 한도 초과
        }
    }
}

문제 3: 컴포지션으로 로깅 리스트 만들기

List<String>에 요소가 추가될 때마다 "ADD: 값"을 출력하는 LoggingList 클래스를 작성하라. 단, ArrayList를 상속하지 말고 컴포지션으로 구현하며, add, addAll, size 세 메서드만 제공하면 된다. addAll(List.of("a","b")) 호출 시 로그가 정확히 2줄 찍혀야 한다.

정답 보기
java
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

class LoggingList {
    private final List<String> inner = new ArrayList<>();

    boolean add(String s) {
        System.out.println("ADD: " + s);
        return inner.add(s);
    }

    boolean addAll(Collection<String> c) {
        boolean changed = false;
        for (String s : c) changed |= add(s);
        return changed;
    }

    int size() { return inner.size(); }
}

public class Main {
    public static void main(String[] args) {
        LoggingList list = new LoggingList();
        list.addAll(List.of("a", "b"));
        System.out.println("size = " + list.size());
        // 출력:
        // ADD: a
        // ADD: b
        // size = 2
    }
}
연습 문제
  • 문제 1: 도형 계층과 넓이 합계
  • 문제 2: 계좌 계층과 오버라이딩 규칙
  • 문제 3: 컴포지션으로 로깅 리스트 만들기
이전 섹션5 자주 하는 실수 (Tip)6 / 7다음 섹션7 정리