interface, abstract class, concrete class


interface - abstract class - concrete class 패턴은 인터페이스 구현 시 자주 발생하게 되는 중복 구현을 방지하는 패턴이다. 간단하게 중복으로 코드가 작성되는 것을 방지하기 위해 작성된다고 생각하면 될 것 같다.

그 전에 interface와 abstract class가 정확하게 무엇인지, 어떤 차이가 있는지 보겠다.

interface와 abstract class의 공통점

둘 다 선언만 있고 구현 내용이 없는 클래스이다.

그래서 자기 자신을 new를 통해 객체를 생성할 수 없다. abstract class를 extend하거나, interface를 implement 한 자식만이 객체를 생성할 수 있다. 이 말은 상속받은 자식이 구현을 반드시 하도록 해야할 때 사용한다.

interface와 abstract class의 차이점

abstract class

추상클래스는 말 그대로 클래스, interface는 구현하기 전에 메소드에 대한 명세 정도로 생각하면 된다. 그래서 상속을 받을때도 클래스에서는 상속이라고 하지만 interface implement(구현) 한다고 한다. 명세서 정도라고 생각하면 편하겠다.

추상클래스는 abstract 메소드가 하나라도 존재하는 클래스를 의미한다. 그래서 일부는 구현된 메소드도 있고, abstract 키워드가 붙어있는 메소드는 구현이 되어있지 않다.

추상클래스를 상속받는 클래스는 반드시 추상 메소드를 구현해야 한다. 그래서 반드시 자식에서 구현해야 할 메소드가 있을 때 추상 클래스를 쓴다

interface

인터페이스는 구현체 없이 메소드에 대한 명세만 되어있다. 인터페이스를 상속받는 클래스에서는 반드시 인터페이스에 있는 메소드를 다 구현해야 한다.

자바는 단일 상속을 지원하기 때문에 추상클래스는 단일 상속이지만, interface를 사용하면, implements를 구현하는 부분에서 extends 또한 사용할 수 있다.

즉 다중 상속이 가능해진다.

정리하자면 인터페이스는 ‘이런 이런 메소드 쓸거야!(요구사항)’ 만 써놓고 가져다가 반드시 선언된 그대로 모두 구현하면 된다.

추상클래스는 ‘이런 이런 메소드가 있는데 가져다 쓰거나 오버라이드 하거나, abstract가 붙은 메소드는 반드시 구현하면 된다.

용도

용도를 설명하기 위해서는 다형성을 짚고 넘어가야 한다.

다형성은 같은 개념의 동작을 객체/구현체마다 다른 형태로 구현할 수 있는 성질이다.

  1. 인터페이스를 언제 쓰는가? 동물은 종마다 다르게 운다. 그래서 운다 라는 틀만 만들어놓고 종마다 틀 안을 다르게 구현하는 것이다.

반드시 구현체(동물)들은 이 운다는 메소드가 구현이되어야 한다. 한 종의 우는 방법이 달라져도 다른 종에는 영향이 없다.

  1. 추상화 클래스는 언제 쓰는가? 야생고양이가 새끼를 낳았다고 하고, 새끼는 집고양이가 되었다고 해보자.
  야생고영(부모클래스)
  - 자기(메소드)
  - 집에서 살기 (추상화 메소드)
  새끼고영(자식클래스)
  - 자기(메소드)
  - 집에서 살기 (메소드)

야생 고영은 집에서 사는 법은 모르지만, 새끼 고영이 집에서 사는 법을 알려주기 위해 추상화 메소드로 만들었다.

야생 고영은 자는 법을 알고, 자식에게 그대로 전수했다. 하지만 새끼고영은 야생고영과 자는 법이 다를 수도 있다.(Override)

새끼 고영은 집 생활을 하며 집에서 노는 법을 추가로 터득했다.(부모 클래스보다 많은 메소드가 구현)

정리하면 인터페이스는 다형성에, 상속은 부모-자식관계로 부모가 갖고 있는 기능을 물려주거나, 자식이 기능을 더 추가하거나, 부모가 갖고 있는 기능을 변형할 수 있다.

해결하고자 하는 문제

  1. 구현해야 할 클래스에 대한 인터페이스가 정해진 상태이다.
  2. 정해진 인터페이스를 통해 구현해야 할 클래스가 여러개이다.
  3. 인터페이스 API 중 일부가 모두 같은 구현부를 같게 된다.(중복이 생긴다)

즉 중복해서 코드가 작성되는 상황이 생긴다는 말이다.

해결 방법

인터페이스를 구현 할 때 구현해야 하는 함수 중에서 중복되는 함수들을 abstract class에 넣어서 곧바로 인터페이슬 구현하려고 할 때 발생할 수 있는 중복 구현을 방지한다.