추상 클래스와 인터페이스의 차이는 인기 있는 인터뷰 질문 중 하나입니다. 추상 클래스와 인터페이스는 자바 프로그래밍 언어의 핵심 부분입니다. 인터페이스를 선택할지 추상 클래스를 선택할지는 모든 아키텍트가 직면하는 설계 결정입니다. 지난 글에서는 자바 인터페이스와 추상 클래스에 대한 가능한 한 많은 세부 정보를 제공했습니다. 이번 글에서는 추상 클래스와 인터페이스의 차이점 및 언제 인터페이스를 추상 클래스보다 사용해야 하는지, 그 반대의 경우에는 언제어떻게 사용해야 하는지에 대해 배워보겠습니다.
추상 클래스와 인터페이스의 차이
abstract
키워드는 추상 클래스를 생성하는 데 사용되며 메서드와 함께 사용할 수 있지만interface
키워드는 인터페이스를 생성하는 데 사용되며 메서드와 함께 사용할 수 없습니다.- 서브클래스는 추상 클래스를 확장하기 위해
extends
키워드를 사용하며, 서브클래스가 추상 클래스인 경우에도 추상 클래스에 선언된 모든 메서드의 구현을 제공해야 합니다. 반면에 서브클래스는 인터페이스를 구현하기 위해implements
키워드를 사용하고 인터페이스에 선언된 모든 메서드에 대한 구현을 제공해야 합니다. - 추상 클래스는 구현을 가진 메소드를 가질 수 있지만 인터페이스는 절대적인 추상화를 제공하며 어떠한 메소드 구현도 가질 수 없습니다. Java 8부터는 인터페이스에도 디폴트 메소드와 정적 메소드를 생성할 수 있습니다.
- 추상 클래스는 생성자를 가질 수 있지만 인터페이스는 생성자를 가질 수 없습니다.
- 추상 클래스는 일반적인 자바 클래스의 모든 기능을 가지고 있지만 인스턴스화 할 수는 없습니다. 추상 클래스를 추상화하려면
abstract
키워드를 사용할 수 있지만 인터페이스는 완전히 다른 유형이며, 오직 public static final 상수와 메소드 선언만 가질 수 있습니다. - 추상 클래스의 메소드는 public, private, protected, static과 같은 접근 제어자를 가질 수 있지만 인터페이스의 메소드는 암시적으로 public과 abstract이며 다른 접근 제어자를 사용할 수 없습니다.
- A subclass can extend only one abstract class but it can implement multiple interfaces.
- 추상 클래스는 다른 클래스를 확장하고 인터페이스를 구현할 수 있지만 인터페이스는 다른 인터페이스만 확장할 수 있습니다.
- 추상 클래스에
main()
메소드가 있다면 실행할 수 있지만 인터페이스는 main 메소드 구현이 불가능하기 때문에 실행할 수 없습니다. - 인터페이스는 하위 클래스에 대한 계약을 정의하는 데 사용되며, 추상 클래스도 계약을 정의하지만 하위 클래스에서 사용할 수 있는 다른 메소드 구현을 제공할 수 있습니다.
인터페이스와 추상 클래스의 차이점에 대해서는 여기까지입니다. 이제 인터페이스와 추상 클래스를 언제 사용해야 하는지 알아보도록 하겠습니다.
인터페이스 또는 추상 클래스
서브클래스에 대한 계약을 제공하기 위해 인터페이스 또는 추상 클래스 중 어느 것을 선택해야 할지는 설계 결정이며 많은 요소에 따라 달라집니다. 언제 인터페이스가 가장 적합한 선택인지와 언제 추상 클래스를 사용할 수 있는지 살펴보겠습니다.
- Java는 다중 클래스 수준 상속을 지원하지 않으므로 모든 클래스는 하나의 슈퍼클래스만 확장할 수 있습니다. 그러나 클래스는 여러 인터페이스를 구현할 수 있습니다. 따라서 대부분의 경우 인터페이스는 클래스 계층 구조와 계약을 제공하기 위한 좋은 선택입니다. 또한 인터페이스를 기반으로 코딩하는 것은 자바에서의 코딩에 대한 최상의 관행 중 하나입니다.
- 계약에 많은 메서드가 있는 경우 추상 클래스가 더 유용합니다. 모든 서브클래스에 공통인 일부 메서드에 대한 기본 구현을 제공할 수 있기 때문입니다. 또한 서브클래스가 특정 메서드를 구현할 필요가 없는 경우 인터페이스의 경우에는 구현을 제공해야 하지만 구현이 필요하지 않고 구현이 비어있는 블록인 경우에는 추상 클래스에서는 구현을 피할 수 있습니다.
- 기본 계약이 계속 변경된다면 인터페이스는 문제를 일으킬 수 있습니다. 인터페이스에 추가 메서드를 선언하려면 모든 구현 클래스를 변경해야 하지만 추상 클래스에서는 기본 구현을 제공하고 새로운 메서드를 실제로 사용할 구현 클래스만 변경할 수 있습니다.
추상 클래스와 인터페이스 모두 사용
인터페이스와 추상 클래스를 함께 사용하는 것이 시스템을 설계하는 가장 좋은 방법입니다. 예를 들어, JDK의 java.util.List
는 많은 메서드를 포함하는 인터페이스이므로, List 인터페이스의 모든 메서드에 대한 스켈레톤 구현을 제공하는 추상 클래스 java.util.AbstractList
가 있습니다. 이렇게 하면 어떤 하위 클래스든 이 클래스를 확장하고 필요한 메서드만 구현할 수 있습니다. 항상 기본으로 인터페이스를 시작하고 모든 하위 클래스가 구현해야 하는 메서드를 정의한 다음, 특정 하위 클래스만 구현해야 하는 메서드가 있는 경우 기본 인터페이스를 확장하고 해당 메서드를 포함하는 새 인터페이스를 만들 수 있습니다. 하위 클래스는 요구 사항에 따라 기본 인터페이스 또는 하위 인터페이스 중 선택하여 구현할 수 있습니다. 메서드의 수가 많이 증가하는 경우, 하위 인터페이스를 구현하는 스켈레톤 추상 클래스를 제공하여 하위 클래스가 인터페이스와 추상 클래스 중 선택할 수 있도록 하는 것도 나쁘지 않은 생각입니다.
자바 8 인터페이스 변경
자바 8부터 인터페이스에서 메소드 구현이 가능합니다. 인터페이스에서 기본 메소드와 정적 메소드를 만들고 그에 대한 구현을 제공할 수 있습니다. 이는 추상 클래스와 인터페이스 사이의 간격을 줄였으며 이제 인터페이스가 가는 길입니다. 왜냐하면 새 메소드에 대한 기본 구현을 제공함으로써 더 확장할 수 있기 때문입니다. 자세한 내용은 Java 8 인터페이스 기본 정적 메소드를 확인하십시오.