Skip to content

Latest commit

 

History

History
98 lines (87 loc) · 4.38 KB

20.추상 클래스보다는 인터페이스를 우선하라.md

File metadata and controls

98 lines (87 loc) · 4.38 KB

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

인터페이스 vs. 추상 클래스

  • 공통된 목적
    • Java의 다중 구현 메커니즘.
    • 인스턴스 메서드를 구현하여 제공 가능
  • 구현에서 차이
    • 추상 클래스를 구현 ➡ 추상클래스의 하위 클래스. 단일 상속
    • 인터페이스를 구현 ➡ 같은 타입(계층 ❌). 다중 상속

인터페이스의 장점 🔍

  • 기존 클래스에서 새로운 인터페이스 쉽게 구현 가능
    • implements로 선언을 추가하고, 요구되는 메서드 구현
    • 추상 클래스를 기존 클래스에 추가하는 경우, 계층 구조에 대해 확인할 필요가 있음
  • 믹스인(mixin) 정의에 적합
    • 믹스인: 클래스가 구현할 수 있는 타입. 믹스인을 구현한 클래스에서는 주된 타입외에도 특정 선택적 행위 제공 가능
    public class Count implements Comparable<Count>{
      
      @Override
      public int compareTo(Count o) { // 믹스인
          return 0;
      }
      
      public void increase() { // 주된 타입
          this.number++;
      }
    }
    • 두개 이상의 추상 클래스로는 믹스인을 삽입하기 어려움
  • 계층구조가 없는 타입 프레임워크 생성 가능
    public interface TikToker {
        Video dance(Music music);
    }
    
    public interface Youtuber {
        StreamService broadcast();
    }
    
    public interface Influencer extends TikToker, Youtuber { // 유튜버+틱톡커인 인플루언서 타입 새롭게 정의!
        Video dance(Music music);
        StreamService broadcast();
    }
    • n개의 속성이 존재할 때, 추상클래스로 구현하는 경우 2^n만큼의 조합의 수
  • 래퍼 클래스 관용구와 궁합이 좋음
    • 기능 향상 시키는 안전하고 강력한 수단

인터페이스의 default 메서드 특징 정리

  • Java 8부터 제공
  • @implSpec 태그로 문서화하기
  • equalshashCode는 정의 불가
  • 인스턴스 필드 선언 불가
  • public이 아닌 정적 멤버 선언 불가(private 정적 메서드는 예외)

인터페이스 장점과 추상 클래스의 장점 모두 활용하기

인터페이스를 사용하라는거 아니였나요? 왜 둘다 활용해야하죠??🧐

➡️ 복잡한 인터페이스의 경우, 매번 구현해야하는 수고를 덜 수 있기 때문!🤓

  • 인터페이스의 장점 + 추상 클래스의 장점(템플릿 메서드 패턴)
    • 인터페이스의 장점 활용하기: 타입을 쉽게 정의, 디폴트 메서드 제공
    • 추상 클래스의 장점 활용하기: 추상(골격 구현) 클래스에서 남은 메서드 중 필요한 메서드 구현
  • 네이밍 방법: Abstract+Interface명 (ex. AbstractCollection, AbstractSet)

골격 구현 방법(난이도 下)

1. 인터페이스에서 다른 메서드들의 구현에 사용되는 기반 메서드 선정하기
기반 메서드는 골격 구현에서 추상 메서드가 된다. Lecture클래스를 잘 살펴보자...

public interface Lecture {
    public boolean equals();
    public int getSize(); // isEmpty()를 구현할 때 사용될거 같다! 기반 메서드로 선정!
    public boolean isEmpty();
}

2. 기반 메서드들을 사용해 직접 구현할 수 있는 메서드들을 모두 디폴트 메서드로 제공하기

public interface Lecture {
    public boolean equals(); // (default 메서드 특징) equals와 hashCode는 default 메서드로 정의 불가하다는 점 잊지 말자
    public int getSize();
    default boolean isEmpty() { // 기반 메서드인 getSize()를 사용해 디폴트 메서드로 변경
        return getSize() == 0;
    }
}

3. 기반 메서드나 디폴트 메서드로 만들지 못한 메서드가 남아있다면, 해당 인터페이스를 구현하는 골격 구현 클래스 생성
필요하다면 public이 아닌 필드와 메서드를 추가할 수 있다. 반대로 인터페이스에서 모두 기반 메서드와 디폴트 메서드로 만들 수 있다면, 골격 구현을 할 필요는 없다.

public abstract class AbstractLecture implements Lecture{ // 클래스 명명 규칙 잊지말자
    @Override
    public boolean equals() { // 남은 메서드를 구현하자
    }
}

마지막으로 골격 구현은 기본적으로 상속이므로, 설계 및 문서화 지침을 모두 따라야 함을 잊지말자.