다형성을 사용하기 위해 여기서는 상속 관계를 사용한다. Animal
(동물) 이라는 부모 클래스를 만들고 sound()
메서드를 정의한다. 이 메서드는 자식 클래스에서 오버라이딩 할 목적으로 만들었다.
Dog, Cat, Caw
는 Animal
클래스를 상속받았다. 그리고 각각 부모의 sound()
메서드를 오버라이딩 한다.
public class AnimalPolyMain1 {
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
Caw caw = new Caw();
soundAnimal(dog);
soundAnimal(cat);
soundAnimal(caw);
}
//동물이 추가 되어도 변하지 않는 코드
private static void soundAnimal(Animal animal) {
System.out.println("동물 소리 테스트 시작");
animal.sound();
System.out.println("동물 소리 테스트 종료");
}
}
soundAnimal(dog)
를 호출하면soundAniaml(Animal animal
메서드에 Dog
인스턴스가 전달된다.
Animal animal = dog
로 이해하면 된다. 부모는 자식을 담을 수 있다. Animal
은 Dog
의 부모다.animal.sound()
메서드를 호출한다.animal
변수의 타입은 Animal
이므로 Dog
인스턴스에 있는 Animal
클래스 부분을 찾아서 sound()
메서드를 실행한다. 그런데 하위 클래스인 Dog
에서 sound()
메서드를 오버라이딩 했다. 따라서 오버라이딩한 메서드가 우선권을 가진다.Dog
클래스에 있는 sound()
메서드가 호출된다.이 코드이 핵심은 Animal animal
이다.
animal
변수는 자식인 Dog, Cat, Caw
의 인스턴스를 담을 수 있고, 참조할 수 있다.animal.sound()
를 호출해도 Dog.sound(), Cat.sound(), Caw.sound()
와 같이 각 인스턴스의 메서드를 호출할 수 있다. 만약 자바에 메서드 오버라이딩이 없었다면 모두 Animal
의 sound()
가 호출되었을 것이다.다형성 덕분에 이후에 새로운 동물을 추가해도 코드를 그대로 재사용할 수 있다.
새로운 기능이 추가되었을 때 변하는 부분을 최소화 하는 것이 잘 작성된 코드이다. 이렇게 하기 위해서는 코드에서 변하는 부분과 변하지 않는 부분을 명확하게 구분하는 것이 좋다.
Animal
클래스를 생성할 수 있는 문제Animal
클래스는 동물이라는 클래스이다. 이 클래스를 직접 생성해서 사용할 일이 있을까? 예) Animal animal = new Animal();
동물이라는 추상적인 개념이 실제로 존재하는 것은 이상하다. 사실 이 클래스는 다형성을 위해서 필요한 것이지 직접 인스턴스를 생성해서 사용할 일은 없다.
하지만 Animal
도 클래스이기 때문에 인스턴스를 생성하고 사용하는데 아무런 제약이 없다. 누군가 실수로 new Animal()
을 사용해서 Animal
의 인스턴스를 생성할 수 있다는 것이다. 이렇게 생성된 인스턴스는 작동은 하지만 제대로된 기능을 수행하지는 않는다.