Search
Duplicate

아이템 20 - 추상 클래스보다는 인터페이스를 우선하라

작성자
챕터
4장 - 클래스와 인터페이스
최종 편집
2023/07/22 04:03
생성 시각
2023/07/20 14:04

개요

인터페이스와 추상 클래스 모두 자바가 제공하는 다중 구현 메커니즘이다. 각 메커니즘이 가진 차이점과 장단점에도 불구하고 왜 인터페이스를 우선해야하는지 알아보자

개념 및 용어

mix-in interface

믹스인을 구현한 클래스에 원래의 “주된 타입” 외의 선택적 행위(기능)을 제공하는 인터페이스
ex. Comparable 인터페이스를 구현한 클래스의 인스턴스들은 서로의 순서를 정할 수 있다.

skeletal implementation

필요한 구현을 인터페이스의 디폴트 메서드 혹은 추상 클래스로 미리 구현한 것

내용

추상 클래스

추상 클래스를 구현한 클래스는 반드시 추상 클래스의 하위 클래스가 된다.
기존 클래스위에 새로운 추상 클래스를 끼워넣기 어렵다.
현실에는 계층을 구분하기 어려운 개념도 존재한다.

인터페이스

인터페이스의 명세대로 잘 구현하기만 한다면, 다른 클래스를 상속했더라도 같은 타입(해당 인터페이스의 구현 클래스)으로 취급된다.
기존 클래스에 새로운 인터페이스를 구현하기 용이하다.
계층구조가 없는 타입 프레임워크를 만들 수 있다.
믹스인 정의에 알맞다.
public interface Developer { void work(); void getSalary(Integer salary); default void workOvertime() { System.out.println("What the fuck"); } }
Java
복사
default method 사용 가능
public class DeveloperImpl implements Developer { public void work() { System.out.println("Programming"); } public void getSalary(Integer salary) { System.out.println("I got " + salary); } }
Java
복사
DeveloperImpl 구현
public interface Marketing { void makePPT(); }
Java
복사
public class DeveloperImpl implements Developer, Marketing { @Override public void programming() { System.out.println("Programming"); } public void getSalary(Integer salary) { System.out.println("I got " + salary); } public void makePPT() { System.out.println("makePPT"); } }
Java
복사
기존의 클래스인 DeveloperInpl에 새로운 mix-in interface인 Marketing을 (추가) 구현
// Developer interface에 대한 골격 구현 추상 클래스 public abstract class AbstractDeveloper implements Developer { public void programming() { System.out.println("Implement programming method in skeletal implementation class"); } public void getSalary(Integer salary) { System.out.println("salary in skeletal implementation class" + salary); } }
Java
복사
public class DeveloperImpl implements Developer { // 다음의 inner class는 골격 구현 클래스를 상속하고, 구현 클래스 DeveloperImpl로부터 인터페이 스의 구현을 위임받는다. private static class AbstractDeveloperDelegator extends AbstractDeveloper { @Override public void programming() { System.out.println("DeveloperImpl call programming method in AbstractDeveloper by using delegation pattern"); } } AbstractDeveloperDelegator abstractDeveloperDelegator = new AbstractDeveloperDelegator(); @Override public void programming() { abstractDeveloperDelegator.programming(); } @Override public void getSalary(Integer salary) { abstractDeveloperDelegator.getSalary(salary); } }
Java
복사
위와 같은 방식으로, Developer의 구현 클래스인 DeveloperImpl은 단일 상속의 문제로부터 벗어날 수 있으며, 여러 인터페이스와 추상클래스로부터 기능을 물려받을 수 있는 확장성을 가진다.

결론

추상 클래스로 할 수 있는 대부분의 일은 인터페이스로 할 수 있고, 디폴트 메서드와 골격 구현 클래스 제공 등의 방식으로 확장성을 높이고, 다중 상속의 장점을 제공할 수 있는 인터페이스를 사용하자!

질문

골격 구현의 범위는 어디까지?

참고자료