자바) 객체지향 개념 - 다형성에 대해서 (개념과 예시로 이해)
객체지향 개념은 캡슐화, 상속, 추상화, 다형성 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 부모 클래스 타입의 참조변수로 자식 객체를 참조하는 경우엔 그냥 아 이게 다형성이구나 했지만,
메서드를 활용한 다형성 예시를 보면, 다형성으로 얼마나 코드가 재사용성이 뛰어난지 느낄 수 있었다.