JAVA

2025.01.13 (월) 21일차 / 다형성

동준1234 2025. 1. 13. 18:40

다형성은 하나의 참조변수로 여러 다른 객체를 다를 수 있다는 뜻인데, 객체 지향 프로그래밍에서 매우 중요한 개념입니다.

다형성은 말 그대로 하나의 형태(변수, 메소드 등)로 여러가지 형태를 처리할 수 있다는 의미입니다.

예를 들어, 동물이라는 클래스가 있을때 동물은 소리를 낸다는 공통적인 속성을 가지고 있습니다. 그런데 이 동물이 개일때는 멍멍 하고, 고양이는 야옹 하고, 새는 짹짹 소리를 냅니다.

이때, '동물' 이라는 클래스를 참조하는 변수가 개, 고양이, 새 같은 다양한 객체를 다룰 수 있게 해주는 것이 바로 다형성입니다.

 

1. 오버라이딩 (Overriding)

- 오버라이딩은 자식 클래스에서 부모 클래스의 메소드를 재정의하는 방식입니다.

부모 클래스의 메소드가 자식 클래스에서 어떻게 실행될지 결정되며, 실제로 객체가 어떤 타입인지에 따라 실행되는 메소드가 달라집니다.

런타임 다형성(오버라이딩) 예시

- 위 예시에서는 Dog, Cat 이라는 클래스가 Animal 이라는 클래스를 부모 클래스로 설정하고 상속 받고 있습니다.

Dog 클래스는 강아지의 짖는소리, Cat 클래스는 고양이의 우는소리를 출력하고 있습니다. 바로 sound 라는 메소드에서요!

아래 Main 클래스에서는 각 클래스들의 객체를 초기화 하고, 각 객체들의 메소드를 실행하고 있습니다.

Dog 와 Cat 클래스는 sound 메소드를 오버라이딩(재정의)하면서 각기 다른 소리를 출력합니다.

그냥 Animal 이라는 클래스에서 sound 메소드를 실행했다면 각기 다른 소리를 출력하지 않을 것 입니다.

실제로 어떤 객체가 생성되었는지에 따라 메소드가 달라진다는 것이 중요한 점이 되겠습니다.

 

2. 업캐스팅

- 위 코드의 주석 처리를 보면 Animal 타입으로 Dog 객체를 참조하며 업캐스팅 된다고 했는데,

업캐스팅은 자식 클래스로 생성된 객체를 부모 클래스 타입의 참조 변수에 할당하는 것 입니다.

- 부모 클래스 타입의 참조 변수에 자식 클래스 객체를 할당하면 (Animal : 부모 클래스 , dog cat : 자식 클래스) 자식 클래스의 모든 속성에 접근할 수 없고 부모 클래스에 정의된 메소드만 호출할 수 있습니다.

- 자식 클래스의 메소드는 실행되지만, 참조 변수의 타입이 부모 클래스이므로 부모 클래스에 정의된 메소드가 호출됩니다. 오늘 강의시간에 배웠던 메모리 부분을 그림으로 그려 간략하게 설명해보겠습니다.

animal 이라는 클래스와 dog, cat 클래스 안에 sound 라는 메소드가 존재합니다. 그래서 저런식으로 코드를 작성하면 어떤 sound 라는 매소드가 실행될지 모릅니다. 하지만 업캐스팅의 개념과 메모리에 대한 개념을 이해한다면 보다 실행하기 쉽습니다. 먼저 animal 이라는 클래스가 생성됩니다. 이후에 dog 과 cat의 클래스가 생성되고 각각 animal 클래스를 상속받아 자신의 고유한 메소드(sound)를 오버라이딩 합니다. 메모리 상에서 객체의 실제 타입에 따라 각 클래스의 sound 메소드가 실행됩니다.


그렇다면 굳이 업캐스팅을 하지 않고 Dog dog = new Dog(); dog.sound(); 로 간단하게 호출해도 같은 결과가 나오는데 왜 업캐스팅을 써야할까? 에 대한 의문이 생겼습니다. 그 이유는 다형성을 제대로 사용하기 위해서 입니다. 먼저 다형성의 장점에 대해 알아보겠습니다.

 

1. 코드의 유연성

- 하나의 부모타입으로 여러자식 클래스의 객체를 다룰 수 있습니다.

- 다형성을 활용하면 같은 메소드 호출이 객체의 실제 타입에 따라 동작하므로, 다양한 상황에서 동일한 코드를 사용할 수 있습니다.

animal 타입을 사용하면 dog, cat, 또는 다른 동물 클래스 개겣를 유연하게 교체할 수 있습니다.

2. 코드의 재사용성

- 부모 클래스의 메소드를 기반으로 다양한 동작을 정의하여 공통 코드를 재사용할 수 있습니다.

- 이를 통해 중복 코드를 줄이고, 새로운 클래스가 추가되더라도 기존 코드를 수정하지 않아도 됩니다.

- 배열이나 리스트에 다양한 객체를 저장하고 반복문으로 처리할 수 있습니다.

 

3. 유지보수 용이성

- 다형성은 개방-폐쇄 원칙을 따릅니다.

- 코드는 확장에는 열려있고 수정에는 닫혀 있는 구조를 가지게 됩니다.

- 새로운 클래스(기능)을 추가할 때 기존 코드를 수정하지 않아도 되므로, 유지보수가 쉽습니다.

4. 중복 코드 제거 및 간결성

- 공통 동작은 부모 클래스에 정의하고, 세부 동작은 자식 클래스에서 정의하면 중복 코드를 줄일 수 있습니다.

- 메소드 오버라이딩을 통해 부모 클래스의 기본 동작을 수정하지 않고, 필요할 때만 자식 클래스에서 동작을 변경할 수 있습니다.


다형성의 가장 큰 장점은 유연성, 확장성, 재사용성을 제공한다는 점입니다. 이를 통해 코드가 간결해지고 유지보수가 쉬워지며, 객체지향 프로그래밍의 강력한 이점을 누릴 수 있습니다.