다형성 polymorphism (중요!)
: 조상 타입 참조 변수로 자손 타입 객체를 다루는 것
1 조상 타입 참조변수로 자손 타입 인스턴스 참조하기
// 1. 보통 - 참조변수와 인스턴스의 타입이 일치함
SmartTv s = new SmartTv();
// 2. 다형성 - 조상 타입 참조변수로 자손 타입 인스턴스 참조 -> 타입 불일치 -> 에러아님!
Tv t = new SmartTv();
// 3. 자손 타입의 참조변수로 조상 타입의 객체를 가리킬 수 없다. -> 에러
SmartTv st = new Tv();
- SmartTv 리모콘으로 SmartTv를 다루면 모든 기능을 사용할 수 있다.
- Tv 리모콘 (조상) 으로 SmartTv를 다루면 일부 기능만 사용할 수 있다.
- SmartTv 리모콘에있는 일부기능이 Tv에는 없어서 사용할 수 없다 (에러)
💡
Q. 참조 변수의 타입은 인스턴스의 타입과 반드시 일치해야 하는가? A. 아니다. 일치하는 것이 보통이지만 일치하지 않을 수 있다.
Q. 참조 변수가 조상 타입일 때와 자손 타입일 때의 차이점? A. 참조 변수로 사용할 수 있는 멤버의 개수가 달라진다.
Q. 자손 타입의 참조 변수로 조상 타입의 객체를 가리킬 수 있는가? A. 아니다. 허용되지 않는다.
2 참조변수의 형변환
- 사용할 수 있는 멤버의 개수를 조절하는 것
- 조상 자손 관계의 참조변수는 서로 형변환 가능
3 형변환 전에는 반드시 instanceof로 확인해야 함
void doWork(Car c) {
if(c instanceof FireEngine) { // 1. 형변환이 가능하지 확인
FireEngine fe = (fireEngine)c; // 2. 형변환
fe.water();
...
💡
Q. 참조변수의 형변환은 왜 하는가? A. 참조변수(리모콘)을 변경함으로써 사용할 수 있는 멤버의 개수를 조절하기 위해서
Q. instanceof연산자는 언제 사용하는가? A. 참조변수를 형변환 하기 전에 형변환 가능 여부를 확인할 때
다형성 장점 1) 매개변수의 다형성
- 참조형 매개변수는 메서드 호출 시 자신과 같은 타입 또는 자손 타입의 인스턴스를 넘겨줄 수 있다.
class Product {
int price;
Product(int price) {
this.price = price;
}
}
class Tv extends Product {
Tv() {
super(100);
}
public String toString() { return "TV"; }
}
class Computer extends Product {
Computer() {
super(200);
}
public String toString() { return "Computer"; }
}
class Buyer {
int money = 1000;
void buy(Product p) {
if(money < p.price) {
return;
}
money -= p.price;
System.out.println(p + "구입"); // p = p.toString
}
class Test {
public static void main(String args[]) {
Buyer b = new Buyer();
b.buy(new Tv()); // buy(Product p) -> TV구입
b.buy(new Computer()); // buy(Product p) -> Computer구입
/*
b.buy(new Tv)); 문장은 아래와 동일하다
Buyer b = new Buyer();
Product p = new Tv();
b.buy(p);
*/
}
}
다형성 장점 2) 하나의 배열에 여러 종류 객체 저장하기
- 조상타입의 배열에 자손들의 객체를 담을 수 있다.
Product p[] = new Product(3);
p[0] = new Tv();
p[1] = new Computer();
p[2] = new Audio();
예제
class Product {
int price;
int bonusPoint;
Product(int price) {
this.price = price;
bonusPoint = (int)(price/10.0);
}
Product() {}
}
class Tv extends Product {
Tv() { super(100); }
public String toString() { return "tv"; }
}
class Computer extends Product {
Computer() { super(200); }
public String toString() { return "computer"; }
}
class Audio extends Product {
Audio() { super(50); }
public String toString() { return "audio"; }
}
class Buyer {
int money = 1000;
int bonusPoint = 0;
Product[] cart = new Product[10];
int i = 0;
void buy(Product p) {
if(money < p.price) { return; }
money -= p.price;
bonusPoint += p.bonusPoint;
cart[i++] = p;
System.out.println(p+"구입");
}
void summary() {
int sum = 0;
String itemList = "";
for(int i=0; i<cart.length; i++) {
if(cart[i] == null) break;
sum += cart[i].price;
itemList += cart[i] + ",";
}
System.out.println("구입 총 금액: " + sum);
System.out.println("구입 제품: " + itemList);
}
}
class Ex {
public static void main(String args[]) {
Buyer b = new Buyer();
b.buy(new Tv());
b.buy(new Computer());
b.buy(new Audio());
b.summary();
}
}
728x90
반응형
'객체지향 OOP' 카테고리의 다른 글
[자바의정석 기초 객체지향 개념] 인터페이스 (0) | 2022.05.31 |
---|---|
[자바의정석 기초 객체지향 개념] 추상클래스 (0) | 2022.05.30 |
[자바의정석 기초 객체지향 개념] 제어자 static, final, abstract / 접근 제어자 / 캡슐화 (0) | 2022.05.30 |
[자바의정석 기초 객체지향 개념] package, import (0) | 2022.05.30 |
[자바의정석 기초 객체지향 개념] 참조변수 super, 생성자 super() (0) | 2022.05.30 |
댓글