인터페이스 vs 추상 클래스
- 추상 클래스 : 추상 클래스가 정의한 타입을 구현하는 클래스는 반드시 추상 클래스의 하위 클래스가 되어야한다.
- 인터페이스 : 인터페이스에서 정의한 메서드를 모두 정의한 클래스라면 다른 어떤 클래스를 상속했든 상관없이 같은 타입으로 취급.
즉, 인터페이스는 기존 클래스에도 손쉽게 새로운 인터페이스를 구현해넣을 수 있다. 인터페이스가 요구하는 메서드를 구현하고, implements만 추가하면 된다.
추상 클래스의 경우 2개의 클래스가 같은 추상 클래스를 확장하길 원한다면, 그 추상 클래스는 계층 구조상 두 클래스의 공통 조상이어야한다. 새로 추가된 추상 클래스의 모든 자손이 적절하지 않은 상황에서도 이를 상속하게 된다.
믹스인
믹스인이란 클래스가 주기능 외에도 추가적인 기능을 혼합한 것이다.
예시) Comparable
Comparable을 구현할 경우 클래스의 인스턴스끼리의 순서를 정할 수 있게된다. 이처럼 대상 타입의 주된 기능에 선택적 기능을 '혼합'한다고해서 믹스인이라고한다.
인터페이스로는 계층구조가 없는 타입 프레임워크를 만들 수 있다.
가수와 작곡가라는 인터페이스가 있고 이를 확장하는 SingerSongwriter 인터페이스를 만들 수 있다.
public interface Singer {
AudioClip sing(Song s);
}
public interface SongWriter {
Song compose(int chartPosition);
}
public interface SingerSongwriter extends Singer, SongWriter {
AudioClip strum();
void actSensitive();
}
위 코드를 클래스로 같은 구조를 만들려면 속성이 n개라면 지원해야 할 조합의 수는 2^n개가 된다.
-> 계층구조가 비대해진다.
추상 골격 구현 클래스
자바8에서 인터페이스에 디폴트 메소드의 기능을 제공해주면서 중복되는 메서드 구현의 시간을 줄여주었다.
하지만 디폴트 메서드의 경우 여러 단점이 존재하기 때문에 추상 골격 구현 클래스를 제공함으로써 인터페이스와 추상 클래스의 장점을 모두 가져갈 수 있다.
[디폴트메서드의 단점]
- 본인이 만든 인터페이스가 아니면 디폴트 메서드를 추가할 수 없다.
- 인터페이스는 인스턴스 필드를 가질 수 없고 public이 아닌 정적 메서드를 가질 수 없다.
- Object 메소드인 equals와 hashcode를 디폴트 메서드로 제공 안함
인터페이스로는 타입을 정의하고 메소드 구현이 필요한 부분은 추상 골격 구현 클래스에서 구현하는 방식이다.
[골격 구현 작성방법]
- 먼저 인터페이스를 잘 살펴 다른 메서드들의 구현에 사용되는 기반 메서드를 선정한다
- 이 기반 메서드들을 사용해 직접 구현할 수 있는 메서드들을 모두 디폴트 메서드로 제공한다.
- 기반 메서드나 디폴트 메서드로 만들지 못한 메서드가 남아있다면, 이 인터페이스를 구현하는 골격 구현 클래스를 하나 만들어 남은 메서드들은 작성해 넣는다.
public abstract class AbstractMapEntry<K,V> implements Map.Entry<K,V> {
@Override public V setValue(V value) {
throw new UnsupportedOperationException();
}
@Override public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof Map.Entry)) {
return false;
}
Map.Entry<?,?> e = (Map.Entry) o;
return Objects.equals(e.getKey(), getKey()) && Objects.equals(e.getValue(), getValue());
}
@Override public int hashCode() {
return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());
}
@Override public String toString() {
return getKey() + "=" + getValue();
}
}
'Java' 카테고리의 다른 글
[Effective Java] 아이템 27. 비검사 경고(unchecked warning)를 제거하라 (0) | 2022.05.08 |
---|---|
[Effective Java] 아이템 26. Raw타입은 사용하지 말라. (0) | 2022.05.08 |
[Effective Java] 아이템19. 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라 (0) | 2022.04.25 |
[Effective Java] 아이템18. 상속보다는 컴포지션을 사용하라 (0) | 2022.04.25 |
[Effective Java] 아이템 17. 변경 가능성을 최소화하라. (0) | 2022.04.16 |