다형성(polymorphism)은 객체 지향 프로그래밍의 특징 중 하나이다.
interface Predator {
String getFood();
}
interface Barkable {
void bark();
}
class Animal {
String name;
void setName(String name) {
this.name = name;
}
}
class Tiger extends Animal implements Predator, Barkable{
@Override
public String getFood() {
return "apple";
}
@Override
public void bark() {
System.out.println("어흥");
}
}
class Lion extends Animal implements Predator, Barkable{
@Override
public String getFood() {
return "banana";
}
@Override
public void bark() {
System.out.println("으르렁");
}
}
class ZooKeeper {
void feed(Predator predator) {
System.out.println("feed" + predator.getFood());
}
}
// 주목!!
class Bouncer {
void barkAnimal (Barkable animal) { // Animal 대신 Barkable 사용
animal.bark();
}
}
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);
}
}
Bouncer 클래스의 barkAnimal 메서드에 주목하자.
barkAnimal 메서드의 입력 자료형이 Animal에서 Barkable로 변경되었다.
그리고 bark 메서드를 호출하도록 코드를 구성하였다.
위 코드에서 tiger, lion 객체는 각각 Tiger, Lion 클래스의 객체이면서 Animal 클래스의 객체이기도 하고, Barkable과 Predator 인터페이스의 객체이기도 하다.
이러한 이유로 barkAnimal 메서드의 입력 자료형을 Animal에서 Barkable로 바꾸어 사용할 수 있는 것이다.
이렇게 하나의 객체가 여러 개의 자료형 타입을 가질 수 있는 것을 객체 지향 세계에서는 다형성이라 한다.
그러므로 Tiger 클래스의 객체는 여러 가지 자료형으로 표현 가능하다.
Tiger tiger = new Tiger(); // Tiger is a Tiger
Animal animal = new Tiger(); // Tiger is a Animal
Predator predator = new Tiger(); // Tiger is a Predator
Barkable barkable = new Tiger(); // Tiger is a Barkable
여기서 중요한 점은 Predator로 선언된 predator 객체와 Barkable로 선언된 barkable 객체는 사용할 수 있는 메서드가 서로 다르다.
predator 객체는 getFood() 메서드만 호출이 가능하고 마찬가지로 barkable 객체는 bark() 메서드만 호출이 가능하다.
만약 getFood() 메서드와 bark() 메서드를 모두 사용하고 싶다면 어떻게 할까?
1. Predator, Barkable 인터페이스를 구현한 Tiger로 선언된 tigert 객체를 사용한다.
2. getFood, bark 메서드를 모두 포함하는 새로운 인터페이스를 만들어 사용한다.
interface Predator {
String getFood();
}
interface Barkable {
void bark();
}
interface BarkablePredator extends Predator, Barkable {}
코드를 보면 알겠지만 인터페이스는 일반 클래스와 달리 extends를 이용하여 여러 개의 인터페이스를 동시에 상속할 수 있다.
즉 인터페이스는 다중 상속이 지원된다.
인터페이스 다중상속 코드 적용 예시
class Lion extends Animal implements BarkablePredator {
public String getFood() {
return "banana";
}
public void bark() {
System.out.println("으르렁");
}
}
자식 인터페이스로 생성한 객체의 자료형은 부모 인터페이스로 사용하는 것이 가능하다.