"""
동물원(zoo) 의 사육사(zookeeper)가 있다.
육식동물(predator) 이 오면 먹이를 준다(feed).
호랑이(tiger) 가 들어오면 사과를 던져준다(apple).
사자(lion) 가 들어오면 바나나를 던져준다(banana).
"""
class Animal {
String name;
void setName(String name) {
this.name = name;
}
}
class Tiger extends Animal {
}
class Lion extends Animal {
}
class Zookeeper {
void feed(Tiger tiger) {
system.out.println("feed apple");
}
void feed(Lion lion) {
system.out.println("feed banana);
}
public static void main(String[] args) {
Zookeeper zooKeeper = new ZooKeeper();
Tiger tiger = new Tiger();
Lion lion = new Lion();
zooKeeper.feed(tiger);
zooKeeper.feed(lion);
}
feed apple
feed banana
그런데 호랑이와 사자 외 다른 육식 동물들이 온다면?
똑같은 방식으로 feed 메서드를 추가해야하는 불편함과 어려움이 존재한다.
그래서 인터페이스를 사용하여 해결한다.
interface Predator {
}
class Tiger extends Animal implements Predator {
}
class Lion extends Animal implements Predator {
}
class ZooKeeper {
void feed(Predator predator) {
system.out.prinln("feed apple");
}
}
feed 메서드의 입력으로 Tiger, Lion 을 각각 필요로 했지만, 코드 수정으로 인해 이제 predator 로 대체가 가능하다.
tiger 와 lion 은 Tiger, Lion 의 객체지만, 더 크게 Predator 인터페이스의 객체이기도 하기에 이와 같이 Predator 자료형으로 사용할 수 있다.
그리고 현재 코드의 문제점은 먹이를 사과만 줄 수 있다.
getFood 메서드를 추가하여 코드를 수정해보자.
interface Predator {
String getFood();
}
하지만 클래스와 다르게 메서드의 몸통을 선언하지 않는다...
인터페이스의 메서드는 메서드의 이름과 입출력에 대한 정의만 있고 그 내용은 존재하지 않는다.
그 이유는 인터페이스는 "규칙"이기 때문이다.
즉, getFood 메서드는 인터페이스를 implements 한 클래스들이 강제적으로 구현해야 하는 규칙이다.
이제 Predator 인터페이스에 getFood 메서드를 추가하면 Tiger, Lion 의 Predator 인터페이스를 구현할 클래스에서 컴파일 오류가 발생할 것이다.
class Tiger extends Animal implements Predator {
public String getFood() {
return "apple";
}
}
class Lion extends Animal implements Predator {
public String getFood() {
return "banana";
}
}
class ZooKeeper {
void feed(Predator predator) {
system.out.println("feed " + predator.getFood());
}
}