📌 학습 목차
23-1. 다형성
23-2. 다형성 예제
23-1. 다형성
다형성(polymorphism):
여러 가지 형태를 가질 수 있는 능력 / 조상 타입의 참조 변수로 자손 타입의 객체를 다루는 것
•자바에서는 한 타입의 참조 변수로 여러 타입의 객체를 참조함으로써 다형성을 프로그램적으로 구현했으며,
이는 조상 타입의 참조 변수로 자손 타입의 객체를 참조할 수 있는 다형성을 의미함
•생성된 객체를 다루기 위해선 객체 타입과 일치하는 참조 변수를 사용하는 것이 일반적이나,
두 클래스가 서로 상속 관계에 있을 경우 다형성에 의해 조상 타입의 참조 변수로 자손 타입의 객체를 참조하는 타입 불일치가 허용됨
반면 자손 타입의 참조 변수로 조상 타입의 객체를 참조할 경우,
참조 변수가 다룰 수 있는 객체의 멤버 개수가 실제 객체의 멤버 개수보다 많아
객체에 존재하지 않는 멤버를 호출해 에러를 발생시킬 수 있으므로 해당 경우는 허용되지 않음
•같은 타입의 객체를 참조하더라도 참조 변수의 타입에 따라 사용할 수 있는 객체의 멤버 개수가 달라짐
예시) 조상 타입의 참조 변수와 자손 타입의 참조 변수가 각각 자손 타입의 객체를 참조할 경우,
조상 타입의 참조 변수는 조상 클래스에 정의된 멤버 개수만큼의 객체 멤버만 사용할 수 있으나
자손 타입의 참조 변수는 조상 클래스로부터 상속받은 멤버를 포함해 객체의 모든 멤버를 사용할 수 있음
📌 // 1) 참조 변수와 객체의 타입이 일치할 경우
Phone p = new Phone();
UpgradedPhone u = new UpgradedPhone();
📌 // 2) 참조 변수와 객체의 타입이 일치하지 않는 경우
// 2-1) 조상 타입의 참조 변수로 자손 타입의 객체를 참조할 경우
Phone p = new UpgradedPhone();
// 2-2) 자손 타입의 참조 변수로 조상 타입의 객체를 참조할 경우
// UpgradedPhone u = new Phone() -> 에러 발생
1) 참조 변수와 객체의 타입이 일치할 경우
•생성된 Phone 인스턴스와 UpgradedPhone 인스턴스를 다루기 위해 각각 인스턴스 타입과 일치하는 타입의 참조 변수를 사용함
2) 참조 변수와 객체의 타입이 일치하지 않는 경우
•Phone 클래스와 UpgradedPhone 클래스가 서로 상속 관계에 있을 경우,
다형성에 의해 조상인 Phone 타입의 참조 변수 p로 자손 타입의 UpgradedPhone 인스턴스를 참조하는 타입 불일치가 허용됨
단, 자손인 UpgradedPhone 타입의 참조 변수 u로 조상 타입의 Phone 인스턴스를 참조하는 경우는 허용되지 않음
23-2. 다형성 예제
package chap_07;
// 1) 조상 클래스
class Phone5 {
String name;
String type;
int capacity;
int price;
}
// 2) 자손 클래스
class UpgradedPhone6 extends Phone5 {
void useStandBy() {}
void useNameDrop() {}
}
public class _23_Example {
public static void main(String[] args) {
// 3) 참조 변수와 객체의 타입이 일치할 경우
📌 // 3-1) 자손 타입의 참조 변수로 같은 타입의 객체를 참조할 경우
UpgradedPhone6 u1 = new UpgradedPhone6();
System.out.println(u1.name);
System.out.println(u1.type);
System.out.println(u1.capacity);
System.out.println(u1.price);
u1.useStandBy();
u1.useNameDrop();
// 4) 참조 변수와 객체의 타입이 일치하지 않는 경우
📌 // 4-1) 조상 타입의 참조 변수로 자손 타입의 객체를 참조할 경우
Phone5 p = new UpgradedPhone6();
System.out.println(p.name);
System.out.println(p.type);
System.out.println(p.capacity);
System.out.println(p.price);
// p.useStandBy(); -> 에러 발생
// p.useNameDrop(); -> 에러 발생
📌 // 4-2) 자손 타입의 참조 변수로 조상 타입의 객체를 참조할 경우
// UpgradedPhone6 u2 = new Phone5(); -> 에러 발생
}
}
3-1) 자손 타입의 참조 변수로 같은 타입의 객체를 참조할 경우
•Phone5 클래스와 UpgradedPhone6 클래스가 서로 상속 관계에 있을 때
자손인 UpgradedPhone6 타입의 참조 변수 u1으로 같은 타입의 UpgradedPhone6 인스턴스를 참조할 경우,
인스턴스의 모든 멤버를 사용할 수 있음
즉, 6개(name, type, capacity, price, useStandBy(), useNameDrop())의 멤버를 다룰 수 있는 참조 변수 u1은
Phone5 클래스로부터 상속받은 멤버 4개(name, type, capacity, price)와
UpgradedPhone6 클래스에서 추가된 멤버 2개(useStandBy(), useNameDrop())를 포함해
총 6개의 UpgradedPhone6 인스턴스 멤버를 모두 사용할 수 있음
4-1) 조상 타입의 참조 변수로 자손 타입의 객체를 참조할 경우
•조상인 Phone5 타입의 참조 변수 p로 자손 타입의 UpgradedPhone6 인스턴스를 참조할 경우, 인스턴스 멤버 중 4개만 사용할 수 있음
즉, 4개(name, type, capacity, price)의 멤버를 다룰 수 있는 참조 변수 p는
UpgradedPhone6 인스턴스 멤버 중 Phone5 클래스에 정의된 멤버 4개(name, type, capacity, price)만 사용할 수 있음
4-2) 자손 타입의 참조 변수로 조상 타입의 객체를 참조할 경우
•자손인 UpgradedPhone6 타입의 참조 변수 u2로 조상 타입의 Phone5 인스턴스를 참조할 경우,
참조 변수 u2로 다룰 수 있는 멤버가 6개(name, type, capacity, price + useStandBy(), useNameDrop())로
Phone5 인스턴스 멤버 4개(name, type, capacity, price)보다 더 많음
이에 참조 변수 u2가 Phone5 인스턴스에 존재하지 않는 멤버를 호출해 에러를 발생시킬 수 있으므로 해당 경우는 허용되지 않음
Reference
[남궁성의 정석코딩] Java의 정석 기초편 강의
[도우출판] Java의 정석 기초편 / 기본편