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());
    }
}

실행결과

동물 울음 소리: 멍멍
동물 울음 소리: 냐옹
동물 울음 소리: 짹짹
동물 울음 소리: 음머에~

동물 울음 소리를 추가되더라도 중복된 코드를 개선되어 간편하게 코드를 추가하고 호출할 수 있었다.