디자인 패턴의 팩토리 패턴을 공부하던 중 추상 팩토리 패턴과 팩토리 메서드 패턴의 차이에서 의문점이 생겼다. 추상 클래스와 인터페이스는 비슷해보이는데 어떤 차이가 있고, 어떤 상황에서 사용하는지 궁금해졌다.
추상 클래스(Abstract Class)와 인터페이스(Interface)는 모두 자바에서 추상화(Abstraction)를 제공하기 위한 수단이다. 그러나 그 목적과 사용 방법에 있어 몇 가지 중요한 차이점이 있다. 이 차이점을 이해하기 위해 각각의 개념을 자세히 살펴보자.
1. 추상 클래스 (Abstract Class)
정의
•
추상 클래스는 공통적인 특징을 가진 클래스들 간의 상속 계층을 만들기 위해 사용된다.
•
추상 클래스는 abstract 키워드로 선언되며, 하나 이상의 추상 메서드(구현되지 않은 메서드)를 포함할 수 있다.
특징
•
상속: 추상 클래스는 다른 클래스가 이를 상속받도록 설계된다. 클래스는 하나의 추상 클래스를 상속받을 수 있다.
•
구현 가능: 추상 클래스는 추상 메서드뿐만 아니라 구현된 메서드도 포함할 수 있다.
•
필드: 추상 클래스는 인스턴스 변수, 정적 변수, 상수 등을 포함할 수 있다.
•
접근 제어자: 추상 클래스와 그 메서드들은 다양한 접근 제어자(public, protected, private)를 사용할 수 있다.
예시
abstract class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public abstract void makeSound(); // 추상 메서드
public void eat() {
System.out.println(name + " is eating.");
}
}
class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void makeSound() {
System.out.println("Bark");
}
}
Java
복사
2. 인터페이스 (Interface)
정의
•
인터페이스는 클래스가 구현해야 할 메서드의 집합을 정의한다.
•
인터페이스는 interface 키워드로 선언되며, 모든 메서드는 기본적으로 추상적이다.
특징
•
구현: 인터페이스는 클래스가 이를 구현하도록 설계됩니다. 클래스는 여러 인터페이스를 구현할 수 있다.
•
구현 불가: 인터페이스는 인스턴스 변수를 포함할 수 없으며, 모든 변수는 기본적으로 public static final이다.
•
디폴트 메서드: 자바 8부터 인터페이스는 default 키워드로 디폴트 메서드(구현된 메서드)를 포함할 수 있다.
•
정적 메서드: 자바 8부터 인터페이스는 정적 메서드를 포함할 수 있다.
•
접근 제어자: 인터페이스의 모든 메서드는 기본적으로 public이다.
예시
interface Animal {
void makeSound(); // 추상 메서드
default void eat() {
System.out.println("Animal is eating.");
}
}
class Dog implements Animal {
@Override
public void makeSound() {
System.out.println("Bark");
}
}
Java
복사
주요 차이점
특징 | 추상 클래스 | 인터페이스 |
상속 | 단일 상속만 가능 (하나의 부모 클래스만 상속받을 수 있음) | 다중 구현 가능 (여러 인터페이스를 구현할 수 있음) |
구현 | 구현된 메서드를 포함할 수 있음 | 모든 메서드는 추상적이지만, 자바 8부터 디폴트 및 정적 메서드 포함 가능 |
필드 | 인스턴스 변수, 정적 변수, 상수 포함 가능 | 상수(public static final 변수)만 포함 가능 |
접근 제어자 | 다양한 접근 제어자 사용 가능 (public, protected, private) | 기본적으로 모든 메서드와 변수는 public |
목적 | 공통 기능의 공유 및 코드 재사용 | 행동의 계약(Contract)을 정의하고 구현 강제 |
사용 시기
•
추상 클래스: 여러 클래스에서 공통적인 기능을 공유하고, 일부 메서드는 재사용 가능하도록 구현하며, 상속 계층을 만들고자 할 때 사용한다. 예를 들어, 여러 종류의 동물 클래스가 공통적으로 가질 메서드와 속성을 정의할 때 유용하다.
•
인터페이스: 클래스가 특정 기능을 반드시 구현하도록 강제하고, 다중 상속의 이점을 활용하고자 할 때 사용한다. 예를 들어, 여러 클래스가 특정 동작(예: Comparable, Runnable)을 구현하도록 요구할 때 유용하다.