인터페이스 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
만큼의 조합의 수
- n개의 속성이 존재할 때, 추상클래스로 구현하는 경우
- 래퍼 클래스 관용구와 궁합이 좋음
- 기능 향상 시키는 안전하고 강력한 수단
- Java 8부터 제공
@implSpec
태그로 문서화하기equals
와hashCode
는 정의 불가- 인스턴스 필드 선언 불가
- 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() { // 남은 메서드를 구현하자
}
}
마지막으로 골격 구현은 기본적으로 상속이므로, 설계 및 문서화 지침을 모두 따라야 함을 잊지말자.