자바를 사용하면서 다형성이라는 키워드를 자주 접했다.
객체지향 프로그래밍을 접할 때 가장 먼저 확인해보는 특징 4가지인 추상화, 상속, 다형성, 캡슐화가 생각이 난다.
위 4가지 특징 중 한가지 특징인 다형성은 무엇이고 자바에서는 이 다형성을 어떻게 설명할 수 있을까?
위키백과에서는 다음과 같이 설명하고 있다.
프로그램 언어의 다형성(多形性, polymorphism; 폴리모피즘)은 그 프로그래밍 언어의 자료형 체계의 성질을 나타내는 것으로, 프로그램 언어의 각 요소들(상수, 변수, 식, 오브젝트, 함수, 메소드 등)이 다양한 자료형(type)에 속하는 것이 허가되는 성질을 가리킨다. 반댓말은 단형성(monomorphism)으로, 프로그램 언어의 각 요소가 한가지 형태만 가지는 성질을 가리킨다.
단형성이라는것도 있네...🫢
다시말해 어떤 객체의 속성이나 기능이 상황에 따라 여러 가지 형태를 가질 수 있는 성질을 의미한다.
실제 자바에서 다형성을 어떻게 적용하는지 보고 다형성의 특징을 확인해보자.
자바에서 다형성을 어떻게 구현할까?
위와 같은 방식을 통해 자바에서는 다형성을 사용할 수 있다.
각각이 무엇을 의미하길래 다형성을 사용한다고 말하는지 이해해보자.
class Parent {
public String name;
Parent() {
this.name = "";
}
Parent(String name) {
this.name = name;
}
void print() {
System.out.println("I'm Parent");
}
}
class Child extends Parent {
Child(String name) {
super(name);
}
}
부모 클래스 Parent와 이를 상속받는 Child 클래스가 존재한다.
자식 클래스가 인수가 존재하는 생성자를 추가해서 생성자를 중복 정의할 수 있다.
위 상황에서는 객체를 재사용하기 쉬워지기 때문에 코드 재사용성이 높아진다!
라는 장점을 생각해볼 수 있다.
오버라이딩 : 상위 클래스의 메서드를 하위 클래스에서 재정의하는 행위를 의미한다.
class Child extends Parent {
Child(String name) {
super(name);
}
@Override
void print() {
System.out.println("I'm Child");
}
}
메소드 오버라이딩을 통해 각각의 자식 객체는 각자에게 맞는 기능을 구현할 수 있다.
업캐스팅 : 자식 클래스 객체를 부모 클래스로 형변환한다.
Parent p = new Child("주노");
위 상황의 경우 자식클래스 Child 객체를 Parent 클래스로 형변환하여 객체를 선언했다. 라고 이해할 수 있다.
이때 print()
메소드 호출 시 System.out.println("I'm Child");
라는 결과가 나오는 것을 볼 수 있다.
이러한 현상을 다음과 같이 서술할 수 있다.
실행시점에 동적 바인딩되어 자식클래스의 멤버함수가 호출된다.
동적 바인딩 : 메서드가 실행 시점에서 성격이 결정되는 바인딩 즉, 다시말해 런타임(Runtime)에 바인딩하는 것을 말한다.
위 구현사례들로부터 다음과 같은 다형성의 특징을 생각해볼 수 있다.
위 예시에서는 상속을 위주로 설명헀지만 인터페이스와 같은 추상화를 이용한다면 다음과 같은 특징도 포함할 수 있다.
객체지향의 특징 중 가장 중요하다고 생각되는 다형성에 대해 알아봤다.
추상적인 이론을 나열하기보다는 이 개념이 어떻게 사용되고 왜 좋은지를 알아보는 시간을 가져보는 데 중점을 뒀기 때문에 다형성 자체에 대한 설명은 부족할 수 있다.
다형성에 대한 개념적 설명은 아래 Reference들을 참고해보는것을 추천한다.