1. 개요

자바에서 **추상 클래스(Abstract Class)**와 **인터페이스(Interface)**는 모두 객체 지향 프로그래밍의 핵심 개념인 추상화(Abstraction)를 구현하기 위한 장치이다. 두 개념 모두 하위 클래스에서 반드시 구현해야 하는 메서드를 정의하여 코드의 규격을 강제하고 다형성을 확보하는 역할을 한다. 그러나 선언 방식과 설계 목적, 메모리 및 다중 상속의 허용 여부 등에서 명확한 차이가 존재한다.


2. 추상 클래스 (Abstract Class)

추상 클래스는 미완성된 설계도에 비유할 수 있으며, abstract 키워드를 사용해 선언한다. 하나 이상의 추상 메서드(구현부가 없는 메서드)를 포함할 수 있으며, 일반 클래스처럼 필드(변수)와 일반 메서드, 생성자도 가질 수 있다.

public abstract class Animal {
    private String name; // 일반 필드

    public Animal(String name) { // 생성자
        this.name = name;
    }

    public void sleep() { // 일반 메서드
        System.out.println(name + "이(가) 잠을 잔다.");
    }

    public abstract void makeSound(); // 추상 메서드 (자식 클래스에서 반드시 구현)
}
  • 인스턴스화 불가: 미완성된 클래스이므로 new Animal()과 같이 직접 객체를 생성할 수 없다.
  • 단일 상속: 자바의 클래스 상속 구조를 따르므로, 자식 클래스는 오직 하나의 추상 클래스만 extends할 수 있다.
  • 목적: 연관성이 높은 클래스들 간의 공통된 상태(필드)와 행위(메서드)를 공유하고 재사용할 때 사용한다.

3. 인터페이스 (Interface)

인터페이스는 극단적으로 추상화된 대표적인 밑그림에 비유할 수 있으며, interface 키워드를 사용해 선언한다. 기본적으로 모든 필드는 public static final(상수)이며, 모든 메서드는 public abstract(추상 메서드)로 동작한다. (Java 8 이후부터는 default 메서드와 static 메서드 구현이 가능하다.)

public interface Swimmable {
    void swim(); // public abstract 생략 가능
}

public interface Flyable {
    void fly();
}
public class Duck implements Swimmable, Flyable {
    @Override
    public void swim() {
        System.out.println("오리가 수영을 한다.");
    }

    @Override
    public void fly() {
        System.out.println("오리가 날아간다.");
    }
}
  • 다중 구현 가능: 클래스는 여러 개의 인터페이스를 동시에 implements할 수 있다.
  • 상태 미보유: 객체의 상태를 나타내는 일반 인스턴스 필드를 가질 수 없다.
  • 목적: 서로 다른 클래스 계층 구조를 가진 객체들에 공통된 행위 규격(접점)을 부여할 때 사용한다.

4. 추상 클래스 vs 인터페이스 주요 차점 비교

구분 추상 클래스 (Abstract Class) 인터페이스 (Interface)
선언 키워드 abstract class interface
상속/구현 키워드 extends implements
다중 지원 여부 단일 상속만 가능 다중 구현 가능
필드 (변수) 일반 변수, 상수 모두 가능 public static final (상수만 가능)
생성자 생성자 존재 가능 생성자 존재 불가
메서드 추상 메서드 + 일반 구현 메서드 추상 메서드 (Java 8 이후 default, static 메서드 가능)
핵심 목적 공통된 기능의 재사용 및 확장 (is-a 관계) 동일한 행위의 규격 및 계약 강제 (can-do 관계)

5. 상황별 선택 기준

두 방식 모두 하위 클래스의 메서드 구현을 강제하지만, 설계하는 목적에 따라 선택이 달라진다.

추상 클래스를 사용하는 경우 (is-a 관계):

  • 명확한 계층 구조가 형성되고, 부모-자식 간에 긴밀한 연관성이 있을 때 사용한다.
  • 하위 클래스들이 공통으로 사용하는 상태(필드)나 구현된 일반 메서드가 많을 때 유용하다.

인터페이스를 사용하는 경우 (can-do 관계):

  • 부모-자식 관계와 관계없이 특정 기능(행위)만을 여러 클래스에 적용하고 싶을 때 사용한다.
  • 다중 상속 효과를 내어 객체 간 결합도를 낮추고 유연한 확장성(디자인 패턴, DI 등)을 확보하고자 할 때 유용하다.

6. 정리

추상 클래스와 인터페이스는 모두 자바에서 추상화를 구현하는 중요한 도구이다. 추상 클래스는 ’무엇인가(is-a)’에 집중하여 공통 상태와 기능을 상속을 통해 확장 및 재사용하는 데 목적이 있다.

인터페이스는 ’무엇을 할 수 있는가(can-do)’에 집중하여 다중 구현을 통해 클래스의 행위 규격을 표준화하는 데 목적이 있다.