- 단일 상속, 하위 클래스(상하 관계)
- 다중 상속, 같은 타입 취급
- EX) Comparable : 자신을 구현한 클래스의 인스턴스끼리는 순서를 정할 수 있다고 선언
public interface Singer {
AudioClip sing(Song s);
}
public interface SongWriter {
Song compose(int chartPosition);
}
public interface SingerSongWriter extends Singer, SongWriter {
void strum();
void actSensitive();
}
public abstract class Singer {
abstract void sing(String s);
}
public abstract class SongWriter {
abstract void compose(int chartPosition);
}
public abstract class SingerSongWriter {
abstract void sing(String s);
abstract void Compose(int chartPosition);
abstract void strum();
abstract void actSensitive();
}
- EX) AbstractCollection, AbstractSet, AbstractList, AbstractMap
1 . 인터페이스를 잘 살펴 다른 메소드들의 구현에 사용되는 기반 메소드를 선정한다. 2 . 기반 메서드들은 골격 구현에서는 추상 메소드가 되고, 기반 메소드들을 사용해 구현할 수 있는 메소드를 모두 디폴트 메소드로 제공한다.
- equals, hashCode는 디폴트 메소드로 제공해선 안된다. 3 . 기반 메소드나 디폴트 메서드로 만들지 못한 메서드가 남아 있다면 이 인터페이스를 구현하는 골격 구현 클래스를 하나 만들어서 작성한다.
- 인터페이스의 메소드 모두가 기반 메소드와 디폴트 메소드가 된다면 골격 구현 클래스로 별도로 만들 필요는 없다. 4 . 골격 구현은 기본적으로 상속해서 사용하는 것을 가정하므로 설계 및 문서화 지침을 모두 따라야 한다.
// 골격 구현 클래스
public abstract class AbstractMapEntry<K,V>
implements Map.Entry<K,V> {
// 변경 가능한 엔트리는 이 메서드를 반드시 재정의해야 한다.
@Override public V setValue(V value) {
throw new UnsupportedOperationException();
}
// Map.Entry.equals의 일반 규약을 구현한다.
@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());
}
// Map.Entry.hashCode의 일반 규약을 구현한다.
@Override public int hashCode() {
return Objects.hashCode(getKey())
^ Objects.hashCode(getValue());
}
@Override public String toString() {
return getKey() + "=" + getValue();
}
}
- 인터페이스 구현 제약 때문에 골격 구현을 추상 클래스로 제공하는 경우가 더 흔하다.
Reference: