interface Predator {
String getFood();
}
class Animal {
String name;
void setName(String name) {
this.name = name;
}
}
class Tiger extends Animal implements Predator{
@Override
public String getFood() {
return "apple";
}
}
class Lion extends Animal implements Predator{
@Override
public String getFood() {
return "banana";
}
}
class ZooKeeper {
void feed(Predator predator) {
System.out.println("feed" + predator.getFood());
}
}
public class Sample {
public static void main(String[] args) {
// TODO Auto-generated method stub
ZooKeeper zk = new ZooKeeper();
Tiger tiger = new Tiger();
Lion lion = new Lion();
zk.feed(tiger);
zk.feed(lion);
}
}
동물 클래스의 종류만큼 feed 메서드가 필요했던 ZooKeeper 클래스를 Predator 인터페이스를 이용하여 구현했더니 단 한 개의 feed 메서드로 구현이 가능해졌다.
여기서 핵심은 메서드가 줄어든 것이 아닌 ZooKeeper 클래스가 동물 클래스에 의존적인 클래스에서 동물 클래스와 상관없는 독립적인 클래스가 되었다는 점이다.
이것이 인터페이스의 핵심이다.
Predator 인터페이스 대신 Animal 클래스에서 getFood 메서드를 추가하고 오버라이딩 해서 사용 가능.
하지만 상속은 자식 클래스가 부모 클래스의 메서드를 오버라이딩 하지 않고 사용 가능하기에 해당 메서드를 반드시 구현해야 한다는 강제성 을 가지 못한다.
여기서 기억해야 할 점은 인터페이스는 인터페이스의 메서드를 반드시 구현해야 하는 강제성을 가짐
자바 8 버전 이후로 디폴트 메서드 (default method)를 사용할 수 있다.
인터페이스의 메서드는 구현체를 가질 수 없지만 디폴트 메서드를 사용하면 실제 구현된 형태의 메서드를 가질 수 있다.
interface Predator {
String getFood();
default void printFood() {
System.out.printf("my food is %s\n", getFood());
}
}
디폴트 메서드는 메서드명 가장 앞에 default라고 표기해야 함.
인터페이스에 디폴트 메서드를 구현하면 인터페이스를 구현한 실제 클래스는 printFood() 메서드를 구현하지 않아도 사용 가능함.
디폴트 메서드 또한 오버라이딩 가능함.