1. 추상 클래스(Abstract Class)
교재 p.278-281 7.1 추상 클래스
1️⃣ 추상 클래스란?
하나 이상의 추상 메서드(구현이 없는 메서드)를 포함하며, 직접 객체를 생성할 수 없는 클래스
주로 상속을 통해 공통된 기능과 구조를 자식 클래스들에게 제공하기 위한 용도로 사용
2️⃣ 추상 클래스의 특징
abstract키워드 사용
- 인스턴스 생성 불가 →
new로 직접 객체를 만들 수 없음.
- 추상 메서드 포함 가능
(추상 메서드는 메서드 선언만 있고 구현이 없음)
- 일반 메서드도 포함 가능
(자식 클래스들이 완전히 동일한 메서드를 가졌을 경우)
- 필드(변수), 생성자도 가질 수 있음
- 상속을 통해서만 사용 (
extends)
- 상속받은 자식 클래스는 추상 메서드를 반드시 구현해야 함
- 공통 코드 재사용 + 구현 강제
3️⃣ 추상 메서드
abstract void run();- 구현부 없음
- 자식 클래스에서 반드시 구현
4️⃣ 추상 클래스 설계 순서 (Bottom-up 방식)
1) 먼저 구체 클래스부터 만든다
- 요구사항을 코드로 바로 표현
- 아직 공통화 고민 ❌
clas sDog {
void eat() {}
void sleep() {}
}
class Cat {
void eat() {}
void sleep() {}
}📌 “일단 돌아가게 만든다”
2) 중복되는 코드와 개념을 발견한다
- 메서드 이름
- 역할
- 책임
eat()
sleep()📌 공통 책임 발견
3) 공통 개념을 추상화한다
- 상위 개념 이름 정의
- 공통 속성과 동작 정리
abstract class Animal {
void eat() {}
void sleep() {}
}📌 중복 제거 + 의미 부여
4) 다를 수 있는 부분만 추상 메서드로 남긴다
abstract class Animal {
void eat() {}
void sleep() {}
abstract void sound();
}📌 “이건 반드시 다를 것이다”
5) 기존 클래스들을 상속 구조로 정리한다
class Dog extends Animal {
@Override
void sound() {
System.out.println("멍멍");
}
}6) 다형성으로 사용한다
Animal a = new Dog();
Animal b = new Cat();📌 설계 완성 단계
설계 순서의 핵심
“미리 추상화하지 말고, 중복이 보일 때 추상화하라.”
❌ Top-down 설계만 고집
⭕ 실제 요구 → 공통점 발견 → 추상화
5️⃣ 추상화(Abstraction)
1) 추상화란?
불필요한 구현은 숨기고, 핵심적인 역할과 공통된 개념만 뽑아내는 것
📌 “무엇을 하는가”에 집중
📌 “어떻게 하는가”는 감춤
2) 추상화의 목적
- 복잡도 감소
- 코드 이해 쉬움
- 변경에 강한 설계
- 다형성 기반
3) 추상화의 대상
- 공통된 책임
- 공통된 행동
- 공통된 역할
4) 추상화 예제 (현실 비유 - 자동차)
abstract class Car {
abstract void move();
}- 내부 엔진 구현은 다름
- 사용자는
move()만 알면 됨
5) 잘 된 추상화 예
abstract class Payment {
abstract void pay (int amount);
}- 카드, 현금, 계좌이체
- “결제한다”라는 역할 중심
6) 잘못된 추상화(주의)
❌ 너무 이른 추상화
❌ 실제 공통점 없는 상위 클래스
❌ 기능 중심이 아닌 구현 중심 추상화
📌 “중복이 보일 때 추상화하라”
7) 추상화와 OOP 4대 특징
개념 | 역할 |
추상화 | 핵심 정의 |
캡슐화 | 내부 은닉 |
상속 | 재사용 |
다형성 | 유연성 |
6️⃣ 실습
1) 추상 메서드
package ex07;
class 판사 {
// 구체적인 행위가 오브젝트마다 다를 때!!
public void 심문(){}
}
class 왕 extends 판사 { // 왕 is 판사
public void 심문(){
System.out.println("왕은 심문한다.");
}
}
class 왕비 extends 판사 {
public void 심문(){
System.out.println("왕비는 심문한다.");
}
}
class 증인 {}
class 모자장수 extends 증인 {
}
class 앨리스 extends 증인 {
}
public class AliceApp {
public static void main(String[] args) {
}
}➡️ 왕과 왕비의 메서드 이름은 같지만, 구체적인 행위가 다름 → 추상 클래스에 추상 메서드 구현 → 재정의
2) 일반 메서드
package ex07;
class 판사 {
public void 심문(){}
}
class 왕 extends 판사 { // 왕 is 판사
public void 심문(){
System.out.println("판사는 심문한다.");
}
}
class 왕비 extends 판사 {
public void 심문(){
System.out.println("판사는 심문한다.");
}
}
class 증인 {}
class 모자장수 extends 증인 {
}
class 앨리스 extends 증인 {
}
public class AliceApp {
public static void main(String[] args) {
}
}➡️ 왕과 왕비의 메서드 이름과 구체적인 행위가 완전히 동일하면
package ex07;
class 판사 {
public void 심문(){
System.out.println("판사는 심문한다.");
}
}
class 왕 extends 판사 { // 왕 is 판사
}
class 왕비 extends 판사 {
}
class 증인 {}
class 모자장수 extends 증인 {
}
class 앨리스 extends 증인 {
}
public class AliceApp {
public static void main(String[] args) {
}
}
➡️ 추상클래스에 행위를 끌어올려 일반 메서드를 만듦 → 자식 클래스에는 메서드 없어도 됨
3) 실습 최종
package ex07;
abstract class 판사 {
// 구체적인 행위가 오브젝트마다 다를 때!!
public abstract void 심문();
public void 종료(){
System.out.println("심문을 종료한다.");
}
}
class 왕 extends 판사 { // 왕 is 판사
public void 심문(){
System.out.println("왕은 심문한다.");
}
}
class 왕비 extends 판사 {
public void 심문(){
System.out.println("왕비는 심문한다.");
}
}
abstract class 증인 {
public abstract void 대답();
}
class 모자장수 extends 증인 {
public void 대답(){
System.out.println("모자장수는 대답한다.");
}
}
class 엘리스 extends 증인 {
public void 대답(){
System.out.println("엘리스는 대답한다.");
}
}
public class AliceApp {
public static void main(String[] args) {
// 1. 인스턴스 초기화 (모든 오브젝트를 인스턴스화)
증인 c1 = new 모자장수();
증인 c2 = new 엘리스();
판사 c3 = new 왕();
판사 c4 = new 왕비();
// 2. 실행
c1.대답();
c2.대답();
c3.심문();
c3.종료();
c4.심문();
c4.종료();
}
}
7️⃣ 기억해야 할 포인트!
- 추상클래스는 구체적인 클래스의 타입을 일체시키기 위해 만든다.
- 추상클래스는 abstract를 붙인다.
- 추상클래스는 추상 메서드를 가질 수 있다.
- 추상클래스는 일반 메서드도 가질 수 있다.
- 추상클래스는 new 할 수 없다.
- 추상클래스의 구체적인 클래스의 메서드가 동일하면 추상화 한다.
Share article