4일차에는 자바의 객체지향 핵심 개념인 상속과 다형성,
그리고 이를 확장하는 추상 클래스와 인터페이스를 학습했다.
문법 자체는 익숙했지만,
“왜 이런 구조가 필요한가?”를 기준으로 다시 정리했고
각 개념이 조금 더 또렷해졌다.
1. 클래스 상속의 기본 개념
자바에서 상속은 자식 클래스가 부모 클래스를 선택하는 구조다.
class Child extends Parent { }
상속의 핵심 특징은 다음과 같다.
- 자바는 단일 상속만 허용
- 부모 클래스의 private 멤버는 상속되지 않음
- 서로 다른 패키지라면 default 멤버도 상속 대상에서 제외됨
상속은 코드 재사용을 위한 수단이지만,
그보다 중요한 목적은 객체 간 관계(is-a)를 표현하는 것이다.
2. 부모 생성자 호출과 객체 생성 흐름
모든 객체는 생성자를 통해 생성된다.
자식 객체가 생성될 때는 부모 객체도 함께 생성된다.
자식 생성자의 첫 줄에는 항상 부모 생성자가 호출된다.
public Child() {
super(); // 생략 가능
}
- super()가 생략되면 컴파일러가 자동으로 추가
- 단, 부모 클래스에 기본 생성자가 없으면
- 반드시 super(…)를 명시해야 한다
👉 이 규칙은 객체 생성 순서를 보장하기 위한 장치다.
3. 메소드 재정의(Override)
상속받은 메소드가
자식 클래스의 역할에 맞지 않을 경우 재정의할 수 있다.
재정의 규칙의 핵심만 정리하면:
- 메소드 시그니처는 동일해야 함
- 접근 제한자는 더 좁아질 수 없음
- 새로운 예외를 throws 할 수 없음
@Override
public void method() { }
@Override는 선택이지만,
컴파일 단계에서 실수를 잡아주기 때문에 사실상 필수다.
4. 다형성과 타입 변환
다형성은 “부모 타입 하나로 여러 자식 객체를 다루는 능력”이다.
Parent p = new Child();
이때 중요한 포인트는:
- 접근 가능한 멤버는 부모 기준
- 실행되는 메소드는 자식 기준(재정의된 메소드)
👉 이 구조 덕분에
코드는 바꾸지 않고 동작만 교체할 수 있다.
5. 강제 타입 변환과 instanceof
부모 타입으로 다루던 객체를
다시 자식 타입으로 사용해야 할 경우 강제 타입 변환이 필요하다.
if (parent instanceof Child) {
Child child = (Child) parent;
}
instanceof는
ClassCastException을 예방하기 위한 안전장치다.
6. 추상 클래스 (abstract class)
추상 클래스는
- *공통된 상태와 동작을 가진 “미완성 객체 설계도”**다.
public abstract class Animal {
public abstract void sound();
}
특징:
- 객체 생성 불가
- 필드, 생성자, 일반 메소드 모두 가질 수 있음
- 하위 클래스에 구현을 강제할 수 있음
👉 정체성이 같은 객체들을 묶을 때 적합하다.
7. 인터페이스 (interface)
인터페이스는
객체가 “무엇을 할 수 있는가”에 대한 계약이다.
public interface Payable {
void pay(int amount);
}
특징:
- 상태(필드)를 가질 수 없음
- 다중 구현 가능
- 구현체 교체에 매우 유리
👉 역할/능력 중심 설계에 사용된다.
8. interface에 필드가 없는 이유
인터페이스는 다중 구현이 가능하다.
여기에 상태가 추가되면 다이아몬드 문제가 발생한다.
그래서 자바는:
- 인터페이스에 상태를 허용하지 않음
- 오직 public static final 상수만 허용
👉 메소드는 구현 클래스의 상태로 동작한다.
9. abstract vs interface 한 번에 정리
| 구분 | abstract class | interface |
| 상태 | O | X |
| 상속 | 단일 | 다중 |
| 의미 | 정체성 | 역할 |
| 관계 | is-a | can-do |
핵심
abstract class는 “무엇인가”
interface는 “무엇을 할 수 있는가”
10. 예외 처리
- Checked Exception: 컴파일 단계에서 처리 강제
- Runtime Exception: 개발자 책임
try {
// 위험한 코드
} catch (Exception e) {
// 예외 처리
} finally {
// 항상 실행
}
throws는 예외를 호출한 쪽으로 위임하는 방식이다.
마무리
간단한 예제 코드를 볼 때는 상속, 다형성, abstract, interface 각각의 개념이 비교적 명확하게 이해됐다.
하지만 여러 객체가 얽히고 역할이 많아지는 조금 더 큰 규모의 코드를 설계하기는 어려울 것 같다는 생각이 든다.
결국 이런 개념들은 글로 이해하는 것보다,
직접 코드를 작성하고, 수정하고, 깨뜨려보는 과정을 통해 체화해야 의미가 생길 것 같다.
📚 Reference
- 『혼자 공부하는 자바』, 신용권 저
'Learning Log' 카테고리의 다른 글
| equals가 있는데 hashCode는 왜 필요할까? (0) | 2026.01.27 |
|---|---|
| abstract vs interface: 비슷한데 왜 굳이 둘 다 있을까? (0) | 2026.01.27 |
| [멋사 클라우드 5기] Day 3 - 객체 생성 흐름과 클래스 구조 이해하기 (1) | 2026.01.25 |
| [멋사 클라우드 5기] Day 2 - 배열, Git & GitHub 기본 개념 정리 (0) | 2026.01.25 |
| [멋사 클라우드 5기] Day 1 - Java 개발 환경과 기본 타입 (0) | 2026.01.25 |
