Java 다형성 - 예제 코드 중복 코드 제거하기
예제 코드를 통해서 다형성을 사용하여 개선하여 나아간다.

이전 예제에는 코드 중복이 있었고, 호출하는 입장에서 중복된 코드를 없앨 수 없었다. 이번 글에서는 상속 관계를 사용하여 Animal 동물 이라는 추상화된 부모 클래스를 만들고 sound() 메소드를 정의한다.
자식 클래스 Cat, Dog, Bird 는 Animal 클래스를 상속 받아, 각각 sound() 메소드를 오버라이딩 한다.

다형성 기능을 사용하여 개선
- 다형적 참조
- 메소드 오버라이딩
개선된 예제 코드
Cat, Dog, Bird 그리고 Animal 추상화 클래스 코드 예제 작성하기
Animal.java
package sound;
public class Animal {
public String sound() {
return "동물 소리";
}
}
Cat.java
package sound;
public class Cat extends Animal {
@Override
public String sound() {
return "냐옹";
}
}
Dog.java
package sound;
public class Dog extends Animal {
@Override
public String sound() {
return "멍멍";
}
}
Bird.java
package sound;
public class Bird extends Animal {
@Override
public String sound() {
return "짹짹";
}
}
다음 Main 클래스를 작성하여 soundAnimal 메소드를 만들고 호출해보도록 한다.
AnimalMain.java
package sound;
public class AnimalMain {
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
Bird bird = new Bird();
soundAnimal(dog);
soundAnimal(cat);
soundAnimal(bird);
}
public static void soundAnimal(Animal animal) {
System.out.println("동물 울음 소리: " + animal.sound());
}
}
실행결과
동물 울음 소리: 멍멍
동물 울음 소리: 냐옹
동물 울음 소리: 짹짹
메소드 soundAnimal 하나를 만들어 타입에 대한 문제를 해결한 모습이다.
부모된 Animal 클래스는 Cat, Dog, Bird 다형적 참조로 메소드 매개변수로 해결할 수 있었다.
package sound;
public class AnimalMain {
public static void main(String[] args) {
Animal dog = new Dog();
Animal cat = new Cat();
Animal bird = new Bird();
soundAnimal(dog);
soundAnimal(cat);
soundAnimal(bird);
}
public static void soundAnimal(Animal animal) {
System.out.println("동물 울음 소리: " + animal.sound());
}
}
메인 함수에서 자식 클래스를 부모 클래스로 변경하여도 동일한 동작을 한다.
이는 부모 클래스 변수로 대입하여 자식 클래스에 있는 오버라이딩된 메소드가 우선적으로 호출되는 기능을 이용한 것이다.

main 의 soundAnimal 동작을 보자.
- soundAnimal(bird) 인수를 new Bird 선언한 변수로 전달하였다.
- soundAnimal(Animal animal) 파라미터는 Bird 인스턴스로 전달받는다.
- 메소드 코드에서 animal.sound() 메소드를 호출한다.
- 인스턴스 내부는 sound() 오버라이딩된 메소드를 찾는다.
- 오버라이딩된 메소드는 Bird 타입에 있다.
- Bird 의 sound() 메소드를 호출되어 "짹짹" 소리를 호출한다.
예제 코드의 다형성의 핵심은 Animal animal 영역이다.
- 다형적 참조로 인해 animal 변수는 Dog, Cat, Bird 변수를 참조할 수 있었다. (부모는 자식을 담을 수 있는 성질)
- 메소드 오버라이딩 덕에 animal.sound() 호출하여도 Dog.sound(), Cat.sound(), Bird.sound() 각 인스턴스의 메소드를 자유롭게 호출할 수 있었다.
- 오버라이딩이 없다면 추상화된 Animal 의 sound() 메소드가 호출되었을 것이다.
코드에 새로운 동물 소리 추가
소 울음 소리가 있는 클래스를 만들어 호출해보도록 한다.
Cow.java
package sound;
public class Cow extends Animal {
public String sound() {
return "음머에~";
}
}
AnimalMain.java
package sound;
public class AnimalMain {
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
Bird bird = new Bird();
Cow cow = new Cow(); // 소 울음 소리 추가
soundAnimal(dog);
soundAnimal(cat);
soundAnimal(bird);
soundAnimal(cow);
}
public static void soundAnimal(Animal animal) {
System.out.println("동물 울음 소리: " + animal.sound());
}
}
실행결과
동물 울음 소리: 멍멍
동물 울음 소리: 냐옹
동물 울음 소리: 짹짹
동물 울음 소리: 음머에~
동물 울음 소리를 추가되더라도 중복된 코드를 개선되어 간편하게 코드를 추가하고 호출할 수 있었다.