개발/JAVA

자바) 객체지향 개념 - 다형성에 대해서 (개념과 예시로 이해)

hubaek 2024. 9. 14. 01:02

객체지향 개념은 캡슐화, 상속, 추상화, 다형성 4가지 개념이 핵심이다.

오늘은 4가지 중 다형성에 대해서 알아볼 예정이다.

다형성은 하나의 객체가 여러가지 형태를 가질 수 있는 능력을 말합니다. 

-> 이렇게 말하면 솔직히 이해가 전혀 안된다..

 

하나의 참조변수로 여러 타입의 객체를 참조할 수 있는 것 -> 이또한 어렵다.

그리고 상속과 인터페이스 개념까지 합하여 들어간다.

 

예시로 이해를 해보려고 한다. 

// 부모 클래스 Animal
class Animal {
    // 동물의 소리를 내는 메서드
    public void sound() {
        System.out.println("동물이 소리를 냅니다.");
    }
}

// Animal의 자식 클래스 Dog
class Dog extends Animal {
    // 강아지의 소리를 재정의(오버라이드)
    @Override
    public void sound() {
        System.out.println("강아지가 멍멍 짖습니다.");
    }
}

// 자식 클래스 Cat
class Cat extends Animal {
    // 고양이의 소리를 재정의(오버라이드)
    @Override
    public void sound() {
        System.out.println("고양이가 야옹합니다.");
    }
}

 

Animal클래스에 sound 메서드가 있고  Dog, Cat 클래스는 Animal 클래스를 상속한다. 

오버라이드를 통해서 Animal의 sound메서드를 각 클래스에 맞게 재정의 해준다.

 

일반적으로 아래 코드를 다형성의 예시라고 한다.

public class PolymorphismExample {
    public static void main(String[] args) {

        // 부모 클래스 타입의 참조 변수로 자식 객체를 참조
        Animal animal1 = new Animal();  // Animal 객체
        Animal dog = new Dog(); // Dog 객체
        Animal cat = new Cat(); // Cat 객체
        
        // 같은 메서드가 각 객체 타입에 따라 다르게 동작함
        animal1.sound();  // "동물이 소리를 냅니다."
        dog.sound();     // "강아지가 멍멍 짖습니다."
        cat.sound();     // "고양이가 야옹합니다."
        
    }
}

보통 Animal animal = new Animal();을 해야하지만

다형성으로 Animal dog = new Dog();  / Animal cat = new Cat(); 

이렇게 가능하다. 근데 이렇게 보면 다형성을 알겠지만 그래서 어떻게 활용하는데? 라는 의문이 든다.

 

게임적인 상황으로 예시를 들면 이렇다.

public class PolymorphismExample {
    public static void main(String[] args) {
        // 부모 클래스 타입의 참조 변수로 자식 객체를 참조
        Animal animal1 = new Animal();  // Animal 객체
        Animal dog = new Dog(); // Dog 객체
        Animal cat = new Cat(); // Cat 객체
        
        // 게임 필드 로직
        // 동물을 필드에 생성해야함.
        createAnimal(dog);
        createAnimal(cat);
    }

	// 다형성을 안쓴 예시 
    // 한가지 동물을 생성할 때 마다 1000줄의 코드가 추가 된다.
    public static void createAnimal(Dog dog) {
        dog.sound();
        // 1000줄의 코드가 존재함
        // 로직은 필드에 오브젝트를 생성하는 메서드
    }
    
    public static void createAnimal(Cat cat) {
    	cat.sound();
        // 1000줄의 코드가 존재함
        // 로직은 필드에 오브젝트를 생성하는 메서드
    }
    
}

위 코드는 다형성을 쓰지 않은 코드이다. 

createAnimal 메서드의 코드가 1000줄이라고 가정할 때,  new연산자로 참조변수는 다형성을 적용했지만, 메서드에는 다형성을 적용하지 않아서 각 동물마다 메서드를 만들어주면 한 동물당 1000줄의 메서드를 만들어야 한다..

 

public class PolymorphismExample {
    public static void main(String[] args) {

        // 부모 클래스 타입의 참조 변수로 자식 객체를 참조
        Animal animal1 = new Animal();  // Animal 객체
        Animal dog = new Dog(); // Dog 객체
        Animal cat = new Cat(); // Cat 객체

        // 게임 필드 로직
        //
        // 동물을 필드에 생성해야함.
        createAnimal(dog); 
        createAnimal(cat); 
    }

	// 다형성을 사용한 예시
    // createAnimal(dog)하면 animal객체가 dog로 들어가서 강아지가 짖습니다.
    // createAnimal(cat)하면 animal객체가 cat으로 들어가서 고양이가 야옹합니다.
    public static void createAnimal(Animal animal) {
    	// 동물이 생성될 때 나오는 사운드라고 생각
        // dog.sound();
        animal.sound(); // "crateAnimal(dog)일때 강아지가 멍멍 짖습니다."
        
        // 1000줄의 코드가 존재함
        // 로직은 필드에 오브젝트를 생성하는 메서드
    }
}

다형성을 쓴 예시 

dog와 cat 참조변수도 다형성을 적용하고, createAnimal 메서드 또한 다형성을 적용 했을 때,

dog를 생성할때, createAnimal(dog);를 하면

public static void create Animal(Animal dog)이 호출 되어 dog.sound() 가 나오고, 1000줄의 코드가 적용 될 것이고

cat을 생성할때도, createAnimal(cat); 하면

public static void create Animal(Animal cat)이 호출 되어 기존의 createAnimal 메서드에서 cat.sound() 가 나오고 동물을 필드에 생성하는 1000줄의 코드 로직이 수행될 것이다.

 

따라서,

메서드에서 다형성을 안했을 땐, 동물을 생성할 때 마다, sound()와, 1000줄의 어마무시한 코드를 적어야해서 엄청난 코드의 수가 되지만,

다형성을 적용하면, 하나의 메서드의 animal.sound()와 1000줄의 로직으로  다양한 동물의 사운드와 생성을 할 수 있다.

 

 

처음 말했던 예시에선 Animal 부모 클래스 타입의 참조변수로 자식 객체를 참조하는 경우엔 그냥 아 이게 다형성이구나 했지만,

메서드를 활용한 다형성 예시를 보면, 다형성으로 얼마나 코드가 재사용성이 뛰어난지 느낄 수 있었다.