[Java] Interface와 Abstract Class

j-yong98·2026년 2월 22일

Java

목록 보기
6/7
post-thumbnail

Interface

인터페이스는 객체가 수행할 행위를 정의하는 구조다. 클래스처럼 구현 방식이 아닌 어떤 기능을 제공해야 하는지 명시하는 것이 목적이다. 즉, 인터페이스는 ‘어떻게’가 아닌 ‘무엇’을 정의한다.

Interface 특징

  • 구현 강제
    인터페이스를 구현하는 클래스는 정의된 메서드를 반드시 구현해야 한다. 인터페이스는 기능을 규격화 하여 구현체 간의 일관성을 유지한다.
  • 다중 구현 가능
    Java에서 클래스는 다중 상속을 지원하지 않지만, 인터페이스는 동시에 여러 개를 구현할 수 있다.
  • 행위 중심
    인터페이스는 일반적으로 상태를 갖지 않고 행위만 정의한다. 객체의 내부 구현보다는 외부에 기대하는 기능에 집중하도록 한다. (static final 필드 가능)
  • 일부 기능 확장 (Java 8 이후)
    public interface Logger {
      
      default void log(String msg) {
        System.out.println(msg);
      }
    }
    인터페이스에서도 일부 구현이 가능해졌다.

Interface 장점

  • 느슨한 결합
    Payment pay = new KakaoPayment();
    Payment pay = new NaverPayment();
    인터페이스를 사용하면 구현체가 아닌 추상 타입에 의존하게 된다. 이를 통해 구현체가 변경 되더라도 사용하는 코드의 영향을 최소화할 수 있다.
  • 확장성과 유연성
    인터페이스는 다중 구현이 가능하기 때문에 다양한 구현체를 쉽게 추가할 수 있다.

Interface 단점

  • 공통 상태 관리의 어려움
    인터페이스는 기본적으로 필드를 통한 상태 관리가 어렵다. 그래서 여러 구현체가 공유해야 하는 데이터나 로직이 있다면 코드 중복이 발생할 수 있다.
  • 코드 재사용성 제한
    인터페이스는 행위 중심으로 표현되어 공통 구현을 제공하기 어렵다.
  • 남용 시 구조 복잡도 증가
    모든 클래스를 인터페이스로 분리하면 파일 수, 코드 탐색, 오버엔지니어링이 발생할 수 있다. 만약, 구현체가 여러 개라면 오히려 가독성을 떨어트릴 수 있다.

Interface 예시

public interface Flyable {
  public abstract void fly();
}

public interface Runnable {
  void run();
}

public interface Swimable {
  void swim();
}

public class Bird implements Flyable, Runnable{

  @Override
  public void fly() {
    System.out.println("Bird flies");
  }

  @Override
  public void run() {
    System.out.println("Bird runs");
  }
}

public class Fish implements Swimable{

  @Override
  public void swim() {
    System.out.println("Fish swims");
  }
}

예시처럼 인터페이스는 특정 객체가 수행해야 하는 행위를 정의하는데 적합하다. 기본적으로 선언하는 메소드는 public abstract 이기 때문에 생략이 가능하다. implements 키워드를 통해 구현을 할 수 있다.

Abstract Class

추상 클래스는 일부 구현을 제공하면서, 하위 클래스에게 특정 동작을 구현하도록 강제하는 클래스다. 인터페이스는 ‘무엇’을 정의 했다면, 추상 클래스는 기본 동작은 제공하면서 확장된 구조를 만드는데 목적이 있다.

Abstract Class 특징

  • 추상 메서드와 일반 메서드 혼합 제공
    추상 메서드를 통해 구현을 강제하고, 일반 메서드를 통해 공통된 로직의 중복을 제거할 수 있다.
  • 상태 보유
    필드를 선언하고 상태를 관리할 수 있다.
  • 생성자
    추상 클래스는 인스턴스화가 불가능하지만, 생성자를 가질 수 있고 이는 하위 클래스 초기화에 사용된다.
  • 단일 상속 제한
    Java에서 클래스는 다중 상속을 지원하지 않는다.

Abstract Class 장점

  • 코드 재사용성
    공통 로직을 상위 클래스에 정의하여 코드 중복을 줄일 수 있다.
  • 상태 공유 가능
    필드와 메서드를 통해 하위 클래스가 동일한 상태를 사용할 수 있다.

Abstract Class 단점

  • 다중 상속 불가능
    하나의 클래스를 이미 상속하고 있다면 추가 상속이 불가능하다.
  • 강한 결합도
    상속 구조는 부모 클래스와 강하게 결합되어 변경 영향 범위가 커질 수 있다.
  • 유연성 제한
    역할 기반 설계보다는 계층 중심 설계에 가까워 확장성이 떨어질 수 있다.

Abstract Class 예시

abstract class Animal {

    protected String name;

    public Animal(String name) {
        this.name = name;
    }

    abstract void sound();
    
    void eat() {
        System.out.println(name + " eats food");
    }
}

class Dog extends Animal {

    public Dog(String name) {
        super(name);
    }

    @Override
    void sound() {
        System.out.println("Woof");
    }
}

class Cat extends Animal {

    public Cat(String name) {
        super(name);
    }

    @Override
    void sound() {
        System.out.println("Meow");
    }
}

추상 클래스는 확장된 구조를 갖는데 목적이 있다. 예시를 보면, 공통된 로직은 기본 메서드로 제공하지만, 특정 객체에 따라 달리 동작할 수 있는 부분을 추상 메서드로 제공해 확장성을 높여준다.

0개의 댓글