2025-08-09 14:57
Tags:
추상 클래스 핸드북
객체 지향 프로그래밍(OOP)에서 **추상 클래스(Abstract Class)**는 미완성된 설계도와 같은 역할을 함. 직접 객체(인스턴스)를 생성할 수는 없지만, 다른 클래스들이 상속받아 완성해야 할 공통적인 구조와 규약을 정의하는 데 사용됨.
1. 만들어진 이유: 왜 필요한가?
소프트웨어 개발은 현실 세계의 개념을 코드로 옮기는 과정. 이때 여러 객체들이 공통적인 특징과 기능을 갖지만, 각자 구현 방식이 다른 경우가 많음.
예를 들어, ‘도형’이라는 개념을 생각해봄. 모든 도형은 ‘넓이를 구한다’는 공통적인 기능을 가짐. 하지만 정사각형, 원, 삼각형의 넓이를 구하는 공식은 모두 다름.
이러한 상황에서 추상 클래스가 등장함.
-
공통 규약 강제: ‘도형’ 클래스를 추상 클래스로 만들고 ‘넓이를 구한다’는 기능을 **추상 메서드(Abstract Method)**로 선언함. 이렇게 하면 ‘도형’을 상속받는 모든 하위 클래스(정사각형, 원 등)는 반드시 자신만의 방식으로 ‘넓이를 구하는’ 기능을 구현하도록 강제할 수 있음. 이는 코드의 일관성과 안정성을 높임.
-
코드 중복 제거: 만약 모든 도형이 ‘색상’이라는 공통된 속성을 갖는다면, 이 속성과 관련된 로직(예:
getColor()
)을 추상 클래스에 미리 구현해 둘 수 있음. 하위 클래스들은 이 기능을 다시 작성할 필요 없이 그대로 물려받아 사용하면 되므로 코드 중복이 줄어듦.
비유: 추상 클래스는 ‘자동차 설계도’와 같음. 설계도 자체를 타고 다닐 수는 없지만(객체 생성 불가), 이 설계도를 기반으로 ‘세단’, ‘SUV’, ‘트럭’ 등 구체적인 자동차를 만들어냄(상속). 모든 자동차는 ‘움직인다’, ‘멈춘다’는 공통 기능을 갖지만(추상 메서드), 각 모델의 구체적인 구동 방식은 다름(구현).
2. 구조
추상 클래스는 다음과 같은 요소들로 구성될 수 있음.
-
추상 메서드 (Abstract Method): 선언부(이름, 매개변수)만 있고, 실제 구현 코드가 없는 메서드.
abstract
키워드로 표시하며, 자식 클래스에서 반드시 재정의(Override)해야 함. -
구현된 메서드 (Concrete Method): 일반 클래스처럼 완전하게 구현된 메서드. 자식 클래스가 공통으로 사용할 기능을 미리 정의해 둔 것.
-
필드 (Fields / Member Variables): 클래스의 상태를 저장하는 변수.
-
생성자 (Constructor): 직접 객체를 만들 수는 없지만, 자식 클래스의 객체가 생성될 때
super()
를 통해 호출되어 공통 초기화 로직을 수행함.
3. 사용법
Java 코드를 예시로 추상 클래스의 정의와 사용법을 살펴봄.
추상 클래스 정의하기
Shape
라는 추상 클래스를 정의. 모든 도형은 넓이를 구해야 하므로 getArea()
를 추상 메서드로, 색상을 가지므로 color
필드와 getColor()
메서드를 구현된 형태로 포함.
// Shape.java - 추상 클래스
public abstract class Shape {
String color;
// 생성자
public Shape(String color) {
this.color = color;
}
// 구현된 메서드
public String getColor() {
return color;
}
// 추상 메서드 - 구현부가 없음
public abstract double getArea();
}
추상 클래스 상속 및 구현하기
Shape
추상 클래스를 상속받아 Circle
과 Rectangle
클래스를 만듦. 각 클래스는 자신의 방식대로 getArea()
메서드를 반드시 구현해야 함.
// Circle.java - 자식 클래스
public class Circle extends Shape {
double radius;
public Circle(String color, double radius) {
super(color); // 부모 클래스의 생성자 호출
this.radius = radius;
}
// 추상 메서드 구현 (오버라이딩)
@Override
public double getArea() {
return Math.PI * radius * radius;
}
}
// Rectangle.java - 자식 클래스
public class Rectangle extends Shape {
double width;
double height;
public Rectangle(String color, double width, double height) {
super(color);
this.width = width;
this.height = height;
}
// 추상 메서드 구현 (오버라이딩)
@Override
public double getArea() {
return width * height;
}
}
4. 심화: 추상 클래스 vs. 인터페이스
추상 클래스와 자주 비교되는 개념으로 **인터페이스(Interface)**가 있음. 둘 다 특정 규약을 강제한다는 공통점이 있지만, 사용 목적과 특징에 차이가 있음.
구분 | 추상 클래스 (Abstract Class) | 인터페이스 (Interface) |
---|---|---|
목적 | 관련성이 높은 클래스 간의 **공통된 특징(상태, 행동)**을 공유하고 확장. (IS-A 관계) | 서로 관련 없는 클래스들에게 **특정 기능(행동)**을 부여. (CAN-DO 관계) |
상속/구현 | 단일 상속만 가능 (extends ) | 다중 구현 가능 (implements ) |
멤버 | 추상/구현 메서드, 변수, 생성자 모두 가능 | 기본적으로 추상 메서드, static final 상수만 가능. (Java 8+ 부터 default , static 메서드 추가) |
키워드 | abstract , extends | interface , implements |
비유 | 설계도. (고양이, 개 → 포유류) | 자격증/플러그인. (사람, 로봇 → ‘운전할 수 있음’) |
언제 무엇을 사용할까?
-
여러 클래스가 공통된 상태(변수)나 구현된 기능을 공유해야 한다면 추상 클래스가 적합.
-
서로 다른 종류의 클래스들에게 동일한 기능(메서드 이름)을 약속하고 싶을 때, 또는 다중 상속의 효과가 필요할 때는 인터페이스가 적합.
5. 요약
-
추상 클래스는 미완성 설계도로, 직접 객체를 만들 수 없음.
-
공통 규약을 강제하고 코드 중복을 줄이기 위해 사용됨.
-
추상 메서드와 구현된 메서드를 모두 가질 수 있음.
-
자식 클래스는
extends
로 상속받고, 모든 추상 메서드를 반드시 **재정의(Override)**해야 함. -
‘IS-A’ 관계의 클래스 구조를 설계할 때 유용하며, ‘CAN-DO’ 관계의 인터페이스와는 목적이 다름.
이 핸드북이 추상 클래스를 이해하는 데 도움이 되었기를 바랍니다.
혹시 특정 프로그래밍 언어에서 추상 클래스를 사용하는 방법에 대해 더 자세한 예시가 필요하신가요?