추상 클래스와 인터페이스의 차이

Introduction

추상클래스와 인터페이스는 추후에 완성할 무언가를 미리 정의한다는 공통점을 가진다. 이 때문에 두 가지의 차이가 정확히 무엇인지, 두 가지를 어떨 때 사용해야 하는지 항상 확실하지 않았기 때문에 시간을 내서 정리해보았다.

 

추상클래스와 인터페이스의 차이

  • 인터페이스는 여러 개를 구현할 수 있지만 클래스는 하나만 상속할 수 있다. (단일 상속, 다중 구현)
  • 인터페이스는 인스턴스의 자료형으로 지정할 수 있으나 추상클래스는 그럴 수 없다.
  • 추상클래스는 추상이 아닌(구현부를 포함한) 메소드를 가질 수 있다.
  • 추상클래스는 인스턴스 변수를 선언할 수 있으나, 인터페이스는 static field만 소유할 수 있다.
  • 추상클래스는 constructor를 가질 수 있으나(자식 클래스에서 사용하기 위함), 인터페이스는 가질 수 없다.
  • 추상클래스는 접근 제어자로 public, protected, private 모두 지정 가능하나 인터페이스는 public만 가능하다.
  • 추상클래스는 다른 Reference Type 자료형과 마찬가지로 Object 클래스를 상속한다.

 

언제 무엇을 사용해야 하는가

상속과 구현

  • 상속은 IS-A 관계이다. 즉, 부모 클래스와 자식 클래스는 동등한 종류의 것으로, 자식 클래스는 그 종류 중 하나인 것이다.
    • 또한 ISP(리스코프 치환 원칙)에 의하면, 자식은 부모를 완전히 대체할 수 있어야 하며 자식들 간에는 서로 치환되지 않아야 한다. 즉, A의 자식클래스 B, C, D가 있다면 B이던게 갑자기 C나 D가 되는 일이 발생해서는 안 된다는 것
    • 리스코프 치환 원칙
    • 부모 객체와 이를 상속한 자식 객체가 있을 때 부모 객체를 호출하는 동작에서 자식 객체가 부모 객체를 완전히 대체할 수 있다는 원칙
  • 인터페이스는 HAS-A 관계이다. 즉, 인터페이스는 이를 구현하는 클래스들이 갖는 공통적 특성을 정의하기 위해 사용한다.

 

올바른 사용법

  • 상속은 강한 결합(hard-bounding)을 만들어 내며, 다형성의 장점을 이용하기 어렵게 만듦
  • 따라서, 주로 공통적 특성을 상위의 추상적인 개념(정의)로 분리하고자 할 때에는 인터페이스를 사용
  • 특정 클래스 내 대부분의 메소드를 사용하는 새로운 클래스를 정의하고자 할 때, ISP를 만족할 수 없다면 상속보다는 컴포지션(Composition)을 이용하는 것이 좋다.
    • 컴포지션의 대표적인 예시로는 Wrapper Class가 있다. (ex: int를 field로 소유하는 Integer)
  • 하지만 템플릿 메소드 패턴처럼 추상클래스의 특징을 잘 이용하는 디자인 패턴도 존재한다.