인터페이스 vs 추상 클래스
인터페이스
와 추상 클래스
는 둘 다 공통적인 구조나 동작을 정의하는 데 사용되지만, 사용 목적과 방식에 따라 각각 적합한 상황이 있습니다. 언제 인터페이스
를 사용하고 언제 추상 클래스
를 사용하는지 이해하기 위해, 두 개념의 차이점과 사용 사례를 비교해 보겠습니다.
1. 인터페이스 (Interface)
- 목적: 객체가 가져야 할 행동(메서드)이나 속성(필드)에 대한 계약을 정의합니다. 구현은 제공하지 않고, 그저 "이 객체는 이러한 기능을 가지고 있어야 한다"는 틀을 설정합니다.
- 특징:
- 순수한 추상화: 구현체가 전혀 없으며, 함수나 속성의 시그니처만 정의됩니다.
- 다중 상속 가능: 한 클래스는 여러 개의 인터페이스를 구현할 수 있습니다.
- 객체의 행동을 규정하는 데 사용되며, 여러 클래스에서 동일한 구조나 규칙을 강제하고자 할 때 유용합니다.
- 언제 인터페이스를 사용하나?:
- 객체의 행동만 정의하고, 구체적인 구현은 필요 없을 때.
- 여러 클래스가 동일한 기능을 가져야 하지만, 서로 다른 상속 구조를 가지는 경우.
- 클래스 간의 느슨한 결합을 원할 때. 인터페이스를 사용하면 클래스들이 특정 구현에 의존하지 않고, 더 유연하게 확장 가능.
Circle
과Square
는 각각 자신만의 방식으로draw
메서드를 구현합니다.
interface Drawable {
draw(): void;
}
class Circle implements Drawable {
draw(){
console.log('Drawing a circle');
}}
class Square implements Drawable {
draw() {
console.log('Drawing a square');
}}
2. 추상 클래스 (Abstract Class)
- 목적: 공통적인 구조를 가진 여러 클래스에서 구현을 일부 제공하거나 공통적인 필드 및 메서드를 공유하고자 할 때 사용합니다. 추상 클래스는 일부 메서드는 구현할 수 있지만, 추상 메서드를 포함해 하위 클래스에서 강제적으로 구현해야 합니다.
- 특징:
- 일부 구현을 포함할 수 있습니다. 즉, 추상 메서드와 일반 메서드가 모두 존재할 수 있습니다.
- 상속이 가능하므로 기본적인 동작을 제공하면서 특정 부분은 자식 클래스에서 구체적으로 구현할 수 있습니다.
- 다중 상속이 불가능하며, 한 클래스는 한 개의 추상 클래스만 상속할 수 있습니다.
- 언제 추상 클래스를 사용하나?:
- 공통된 상태(필드)나 기본 동작(메서드)을 여러 클래스에 제공하고, 일부 메서드는 자식 클래스에서 구체화해야 할 때.
- 여러 클래스가 공유하는 기능이 있고, 그 기능의 기본 구현을 제공하려 할 때.
- 객체의 특정 속성이나 메서드를 기본으로 제공하되, 상속받는 클래스에서 이를 구체화하거나 덮어쓰기 할 필요가 있을 때.
Shape
는 공통적인 기능인move
를 제공하고,draw
는 자식 클래스에서 구현을 강제합니다.
abstract class Shape {
// 일반 메서드: 공통적인 기능 제공
move(): void {
console.log("Shape moved");
}
// 추상 메서드: 자식 클래스에서 구현을 강제
abstract draw(): void;
}
class Circle extends Shape {
draw() {
console.log('Drawing a circle');
}
}
class Square extends Shape {
draw() {
console.log('Drawing a square');
}
}
주요 차이점:
특징 | 인터페이스 | 추상 클래스 |
---|---|---|
구현 | 구현이 없음. 오직 메서드 시그니처만 정의 | 일부 메서드는 구현 가능, 일부는 추상 메서드로 구현 강제 |
상속 관계 | 다중 상속 가능 | 단일 상속만 가능 |
필드 포함 여부 | 필드(속성)를 포함할 수 없음 | 필드를 포함할 수 있음 |
용도 | 공통 행동(메서드)를 강제 | 공통 상태와 행동을 제공하고, 일부 동작은 구체화 필요 |
언제 어떤 걸 사용해야 할까?
- 인터페이스를 사용해야 할 때:
- 클래스 간에 공통적인 메서드나 속성 시그니처만 정의하고, 구체적인 구현은 각 클래스에서 다르게 할 때.
- 다중 상속이 필요할 때 (한 클래스가 여러 개의 인터페이스를 구현할 수 있음).
- 강력한 유연성과 결합도를 낮추기 위한 추상화를 원할 때.
- 추상 클래스를 사용해야 할 때:
- 클래스 간에 공통된 필드와 메서드 구현을 제공하면서도, 하위 클래스에서 특정 메서드를 강제적으로 구현해야 할 때.
- 여러 클래스가 공통적인 상태나 기본 동작을 공유해야 할 때.
- 상속을 통한 구조화가 필요하고, 기본 기능을 여러 자식 클래스에서 상속받아 사용할 때.
결론:
- 행동에 대한 계약만 정의하고 싶다면 인터페이스를 사용하세요.
- 공통적인 상태와 기본 동작을 포함하고 싶다면 추상 클래스를 사용하세요.
댓글