자바에서는 둘 이상의 클래스로부터 상속받는 다중 상속(multiple inheritance)을 원칙적으로 지원하지 않는다.
하지만 다중 제어의 관점에서 다중 상속은 권장할 만한 기술이다.
이에 자바에서는 다중 상속의 활용을 위해 인터페이스를 제공한다.
만약 '학생' 클래스와 '여자'클래스가 만들어졌고 '여학생' 클래스가 필요하다면 새로운 클래스로 따로 정의할 필요없이 이미 구현된 학생 클래스와 여자 클래스를 다중 상속 받아서 여학생 클래스를 만들면 된다.
하지만 이렇게 인터페이스 없이 단순하게 다중 상속을 하면 학생의 name 속성과 여자의 name 속성이 충돌을 만들 수 있다.
재정의도 선택적이기 때문에 개발자가 재정의를 깜빡하고 하지 않은 메서드는 오류를 만들 수 있다.
다중 상속의 문제가 발생하지 않도록 다음과 같은 규칙을 만든다.
인터페이스 내에는 변수를 선언 불가(이름 충돌 방지).
상수만 선언 가능하며 묵시적으로 static final이다.
추상 메서드만 선언 가능(하위 클래스에서 재정의를 방지).
추상 클래스처럼 직접 객체를 생성할 수 없다.
인터페이스를 상속받는 하위 클래스에서는 implements 키워드를 사용해서 선언한다.
여러가지 색의 새들이 있다. 참새, 비둘기, 닭, 펭귄이 있는데 닭과 펭귄은 날지 못하는 기능을 가지고 있고, 펭귄은 혼자 남극에 산다는 기능을 가진다고 한다.
bird라는 상위 abstract 클래스에 참새, 비둘기, 닭, 펭귄이 상속받고 있는데 닭과 펭귄은 fly() 메서드가 사용이 안되고 펭귄은 live() 메서드가 재정의 되어야 한다.
그런데 추상 클래스로만 상속을 구현할 때 문제는 fly() 메서드 사용을 모든 하위 클래스에 강제할 수 없기에 개발자의 자율성에 맡긴다. 따라서 누군가는 fly()메서드를 startFly()메서드로 이름을 바꿔 선언할 수도 있고 잘못해서 빠뜨릴 수도 있다. 아니면 닭과 펭귄에는 사용하지도 않는 빈 fly() 메서드를 생성해야 한다.
해결 방안으로는 bird라는 abstract 클래스에는 딱 공통되는 속성과 메서드만 넣는다. 그리고 선택사항의 메서드인 fly()와 live()를 인터페이스 클래스로 만든다.
이렇게 하면 하위 클래스에서는 fly()와 live()를 선택적으로 상속받을 수 있고, fly()와 live()에서 수정해야할 사항이 있으면 그 인터페이스 클래스만 수정을 하면 되기에 유지 보수에 효율적이다.
코드 중복 측면에서는 크게 이점을 찾기 힘들겠지만, 하위 클래스의 수정이 있어도 다른 클래스에 영향을 주지 않기 때문에 유지 보수의 측면에서 도움이 된다.
public interface Live {
public abstract void live();
}
public interface Fly {
public abstract void fly();
}
public abstract class Bird { // 상위 클래스 새
public class Sparrow extends Bird implements Live, Fly { // 참새
public class Pigeon extends Bird implements Live, Fly { // 비둘기
public class Chicken extends Bird implements Live { // 닭
public class Penguin extends Bird implements Live { // 펭귄
@Override
public void live() {
System.out.print("남극에 삽니다.");
}
}