Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

자바(Java) 추상 클래스 vs 인터페이스: 핵심 차이점 완벽 정리

자바(Java)에서 추상화(abstraction)는 추상 클래스(Abstract Class)인터페이스(Interface)를 통해 구현됩니다. 두 방식 모두 하위 클래스 또는 구현 클래스가 반드시 오버라이딩해야 하는 추상 메서드를 포함할 수 있다는 공통점이 있습니다. 하지만 문법적 제약과 설계 목적에서 중요한 차이가 존재합니다. 아래 표에서 추상 클래스와 인터페이스의 주요 차이점을 항목별로 비교해 보겠습니다.

번호구분 기준추상 클래스 (Abstract Class)인터페이스 (Interface)
1지원 메서드추상 메서드와 일반(구체) 메서드를 모두 가질 수 있습니다.기본적으로 추상 메서드만 가질 수 있으며, Java 8부터는 default 메서드와 static 메서드도 허용됩니다.
2다중 상속다중 상속을 지원하지 않습니다.다중 상속(다중 구현)을 지원합니다.
3지원 변수final, non-final, static, non-static 변수를 모두 사용할 수 있습니다.static과 final 변수만 선언할 수 있습니다.
4구현 관계인터페이스를 구현(implement)할 수 있습니다.다른 인터페이스를 구현할 수는 없으며, 확장(extend)만 가능합니다.
5선언 키워드abstract 키워드로 선언합니다.interface 키워드로 선언합니다.
6상속 범위extends 키워드로 다른 클래스를 상속받으면서 동시에 인터페이스를 구현할 수 있습니다.인터페이스만 상속(확장)할 수 있습니다.
7상속 방식extends 키워드를 사용해 상속받습니다.implements 키워드를 사용해서만 구현할 수 있습니다.
8접근 제어private, public 등 모든 종류의 멤버와 접근 제어자를 사용할 수 있습니다.public 멤버만 허용됩니다.

추상 클래스 vs 인터페이스 예제 코드

아래 예제는 하나의 프로그램에서 인터페이스(Animal)와 추상 클래스(Cat)를 각각 구현·상속하여 사용하는 방법을 보여줍니다.

JavaTester.java

public class JavaTester {
    public static void main(String args[]) {
        Animal tiger = new Tiger();
        tiger.eat();
        Cat lion = new Lion();
        lion.eat();
    }
}
interface Animal {
    public void eat();
}
class Tiger implements Animal {
    public void eat(){
        System.out.println("Tiger eats");
    }
}
abstract class Cat {
    abstract public void eat();
}
class Lion extends Cat{
    public void eat(){
        System.out.println("Lion eats");
    }
}

실행 결과

Tiger eats
Lion eats

어떤 것을 선택해야 할까?

두 개념의 선택 기준은 다음과 같이 정리할 수 있습니다.

추상 클래스는 관련 있는 클래스들 간에 공통된 상태(필드)와 부분적으로 구현된 기능을 공유하고 싶을 때 적합합니다. 예를 들어 여러 동물 클래스가 공통으로 사용하는 필드나 일부 완성된 메서드가 필요하다면 추상 클래스가 좋은 선택입니다.

인터페이스는 서로 관련 없는 클래스들에게 특정 기능 수행 능력을 부여하는 계약(contract) 역할이 필요할 때 적합합니다. 또한 Java 8 이후에는 default 메서드 덕분에 인터페이스에서도 기본 구현을 제공할 수 있어 활용 범위가 더욱 넓어졌습니다.

일반적으로 "~이다(is-a)" 관계의 공통 기반을 만들 때는 추상 클래스를, "~할 수 있다(can-do)" 같은 기능 명세를 정의할 때는 인터페이스를 사용하는 것이 자바 설계의 모범 사례로 꼽힙니다.