★ 다형성
- 여러가지 형태를 가질수 있는 능력
- 조상 타입 참조 변수로 자손 타입 객체를 다루는것
- 자손 타입의 참조 변수로 조상 타입의 객체를 가리킬수 없다
class Tv {
boolean power;
int channel;
void power() { power = !power }
void channelUp() { ++channel; }
void channelDown() { --channel; }
}
class SmartTv extends Tv {
String text;
void caption() { // 내용내용... }
}
지금까지 우리가 객체를 생성할땐
Tv t = new Tv();
SmartTv s = new SmartTv();
이렇게 진행했다.
하지만 다형성은 다르다.
Tv t = new SmartTv();
타입이 불일치 하지만 이게 된다.
이게 다형성이다.
- 객체와 참조변수의 타입이 일치할때와 일치하지 않을때의 차이가 무엇이 있을까?
1.
SmartTv s = new SmartTv();
참조 변수와 인스턴스의 타입이 일치할때
2.
Tv t = new SmartTv();
조상 타입 참조변수로 자손 타입 인스턴스 참조
3.
SmartTv s = new Tv();
에러
이미지로 그려보자
SmartTv 타입의 리모콘 (s)과 Tv 타입의 리모콘 (t)가 있다.
당연하게 s는 SmartTv의 기능과 버튼의 갯수가 동일하니 당연히 사용할 수 있다.
그럼 t는 어떨까? t(부모)의 버튼은 5개이고 SmartTv의 기능은 7개이다. 그러면 SmartTv기능중 5개를 사용 할 수 있는것이다.
3번의 경우는 리모콘의 버튼이 Tv보다 많은 기능이 있어서 눌러도 아무 반응이 없는 리모콘이 만들어진다.
????????? 이게 무슨 소리야? 하는 생각을 가지고 몇 번 읽어 보았는가? 정상이다....
장점이지만 장점같이 안들리는 장점이다 하하.. 하지만 확실하게 장점에 속하고 심지어 굉장히 유연한 장점이 될 수 있다.
이야기가 살짝 다른길로 새는 느낌이지만 천천히 생각해보자
우리가 구매자라고 생각해보자
우리는 리모콘과 함께 Tv를 구매하게 되는데 돈이 모자라서 리모콘의 기능이 조금 안좋은것을 샀다.
그래서 리모콘이 SmartTv의 기능을 다 사용하진 못하지만 리모콘의 모든 기능은 제대로 작동할 것이다.
이는 사는 사람 입장에서 기분이 나쁠 수 없다. 왜냐하면 본인이 돈이 모자라서 조금 구형의 리모콘을 샀기 때문이다.
그럼 이번엔 반대로
우리는 리모콘과 함께 Tv를 구매하게 되는데 돈이 남아서 리모콘의 기능이 조금 좋은것을 샀다.
그래서 집에 와서 이것저것 눌러보는데 Tv가 반응을 안한다. 리모콘 설명서에는 완전 멋진 기능을 잔뜩 넣어놨는데 그게 아무것도 작동을 안한다면 무슨 기분일까?
여기서 구매자는 화가 많이 날수 있다. 기껏 비싼 돈 주고 좋은 리모콘을 사왔더니 Tv가 너무 구진것이였다...
이런식으로 다형성을 이해해보는게 좋다.
- 기능이 많지 않은 리모콘으로 화려한 기능이 있는것을 컨트롤에 부족함이 없지만 기능만 많지만 정작 조종하는 Tv가 아무것도 안되는 것이 비교도 안되게 훨씬 불상사가 되는것이기 때문이다.
장점이다...
- 작은것으로 큰것을 다루는 것 = 아 좀 아쉬운데...?
- 큰 걸로 작은걸 다루는것 = 뭐야 이거 왜 안움직여??????!?!?
★ 참조 변수의 형변환
- 사용할 수 있는 멤버의 갯수를 조절하는것
- 조상, 자손 관계의 참조 변수는 서로 형변환 가능
class Car {
String color;
int door;
void drive() {
System.out.println("drive, Brrrr~");
}
void stop() {
System.out.println("Stop!!!");
}
}
class FireEngine extends Car {
void water() {
System.out.println("water!!");
}
}
class Ambulance extends Car {
void light() {
System.out.println("light!!");
}
}
FireEngine f = new FireEngine();
Car c = (Car)f; // 가능. 조상인 Car 타입으로 형변환
FireEngine f2 = (FireEngine)c; // 가능. 자손인 FireEngine타입으로 형변환
Ambulance a = (Ambulance)f; // 에러. 상속관계가 아닌 클래스 간의 형변환 불가
이건 객체 생성이 아니라 형변환을 대입해주는 것이다.
★ instanceof 연산자
- 참조변수의 형변환 가능여부 확인에 사용. 가능하면 true 반환
- 참조변수의 형변환은 조상과 자손만이 가능하다는것을 명심해야한다
- 형변환을 하기전에 반드시 instanceof로 확인 후에 진행한다.
class FireEngine extends Car
class Ambulance extends Car
이렇다고 가정할때
void doWork(Car c) {
if(c instanceof FireEngine) { 형변환을 확인한다.
FireEngine fe = (FireEngine)c; 형변환을 진행한다.
fe.water();
...
}
}
매개변수로 들어간 Car c는 Car의 자손인 FireEngine과 Ambulance도 가능하다.
이때 매개변수가 Ambulance라면 형제인 FireEngine은 형변환이 불가능하기 때문에 꼭 확인을 해야하는것이다
그러면 이런식으로 확인을 하는것이다.
FireEngine fe = new FireEngine();
System.out.println(fe instanceof Object) // true
System.out.println(fe instanceof Car) // true
System.out.println(fe instanceof FireEngine) // true
instanceof로 확인한 모두가 조상과 자손이기 때문에 형변환이 가능하다.
매개변수의 다향성
- 참조형 매개변수는 메소드 호출시, 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨 줄 수 있다.
class Product {
int price;
int bonusPoint;
}
class Tv extends Product {}
class Computer extends Product {}
class Audio extends Product {}
class Buyer {
int money = 1000;
int bonusPoint = 0;
void buy(Tv t) {
money -= t.price;
bonusPoint += t.bonusPoint
}
이런식으로 매개변수를 해놓으면 모든 물품 구매를 담당하는 중복 메소드를 만들어야한다.
}
그래서 매개변수에 애초에 다루고 있는 조상을 타입으로 넣는것이다.
void buy(Product p) {
money -= p.price;
bonusPoint += p.bonusPoint;
}
이렇게 되면 Product는 다형적 매개변수로 인해 자손의 모든 타입이 가능한것이다.
Buyer b = new Buyer();
Tv tv = new Tv();
Computer com = new Computer();
b.buy(tv);
b.buy(computer);
이런식으로 적어넣으면 한가지의 메소드로 다른 타입의 물건들을 타입으로 넣기만 하면 구매가 가능한것이다.
여러 종류의 객체를 배열로 다뤄보자
- 조상 타입의 배열에 자손들의 객체를 담을 수 있다.
Product p1 = new Tv(); Product p[] = new Product[3]
Product p2 = new Computer(); -----> p[0] = new Tv();
Product p3 = new Audio(); p[1] = new Computer();
p[2] = new 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) {
System.out.println("잔액이 부족합니다.");
return;
}
money -= p.price;
bonusPoint += p.bonusPoint;
Cart[i++] = p;
}
}
'Java > 객체 지향' 카테고리의 다른 글
호출 스택(call stack) (0) | 2023.05.08 |
---|---|
메소드(ft . return 문) (0) | 2023.05.08 |
변수의 종류 (0) | 2023.05.08 |
클래스와 객체(feat. 객체 지향 언어의 역사) (0) | 2023.05.04 |
클래스들의 관계. 상속과 포함 (0) | 2023.03.07 |
★ 다형성
- 여러가지 형태를 가질수 있는 능력
- 조상 타입 참조 변수로 자손 타입 객체를 다루는것
- 자손 타입의 참조 변수로 조상 타입의 객체를 가리킬수 없다
class Tv {
boolean power;
int channel;
void power() { power = !power }
void channelUp() { ++channel; }
void channelDown() { --channel; }
}
class SmartTv extends Tv {
String text;
void caption() { // 내용내용... }
}
지금까지 우리가 객체를 생성할땐
Tv t = new Tv();
SmartTv s = new SmartTv();
이렇게 진행했다.
하지만 다형성은 다르다.
Tv t = new SmartTv();
타입이 불일치 하지만 이게 된다.
이게 다형성이다.
- 객체와 참조변수의 타입이 일치할때와 일치하지 않을때의 차이가 무엇이 있을까?
1.
SmartTv s = new SmartTv();
참조 변수와 인스턴스의 타입이 일치할때
2.
Tv t = new SmartTv();
조상 타입 참조변수로 자손 타입 인스턴스 참조
3.
SmartTv s = new Tv();
에러
이미지로 그려보자
SmartTv 타입의 리모콘 (s)과 Tv 타입의 리모콘 (t)가 있다.
당연하게 s는 SmartTv의 기능과 버튼의 갯수가 동일하니 당연히 사용할 수 있다.
그럼 t는 어떨까? t(부모)의 버튼은 5개이고 SmartTv의 기능은 7개이다. 그러면 SmartTv기능중 5개를 사용 할 수 있는것이다.
3번의 경우는 리모콘의 버튼이 Tv보다 많은 기능이 있어서 눌러도 아무 반응이 없는 리모콘이 만들어진다.
????????? 이게 무슨 소리야? 하는 생각을 가지고 몇 번 읽어 보았는가? 정상이다....
장점이지만 장점같이 안들리는 장점이다 하하.. 하지만 확실하게 장점에 속하고 심지어 굉장히 유연한 장점이 될 수 있다.
이야기가 살짝 다른길로 새는 느낌이지만 천천히 생각해보자
우리가 구매자라고 생각해보자
우리는 리모콘과 함께 Tv를 구매하게 되는데 돈이 모자라서 리모콘의 기능이 조금 안좋은것을 샀다.
그래서 리모콘이 SmartTv의 기능을 다 사용하진 못하지만 리모콘의 모든 기능은 제대로 작동할 것이다.
이는 사는 사람 입장에서 기분이 나쁠 수 없다. 왜냐하면 본인이 돈이 모자라서 조금 구형의 리모콘을 샀기 때문이다.
그럼 이번엔 반대로
우리는 리모콘과 함께 Tv를 구매하게 되는데 돈이 남아서 리모콘의 기능이 조금 좋은것을 샀다.
그래서 집에 와서 이것저것 눌러보는데 Tv가 반응을 안한다. 리모콘 설명서에는 완전 멋진 기능을 잔뜩 넣어놨는데 그게 아무것도 작동을 안한다면 무슨 기분일까?
여기서 구매자는 화가 많이 날수 있다. 기껏 비싼 돈 주고 좋은 리모콘을 사왔더니 Tv가 너무 구진것이였다...
이런식으로 다형성을 이해해보는게 좋다.
- 기능이 많지 않은 리모콘으로 화려한 기능이 있는것을 컨트롤에 부족함이 없지만 기능만 많지만 정작 조종하는 Tv가 아무것도 안되는 것이 비교도 안되게 훨씬 불상사가 되는것이기 때문이다.
장점이다...
- 작은것으로 큰것을 다루는 것 = 아 좀 아쉬운데...?
- 큰 걸로 작은걸 다루는것 = 뭐야 이거 왜 안움직여??????!?!?
★ 참조 변수의 형변환
- 사용할 수 있는 멤버의 갯수를 조절하는것
- 조상, 자손 관계의 참조 변수는 서로 형변환 가능
class Car {
String color;
int door;
void drive() {
System.out.println("drive, Brrrr~");
}
void stop() {
System.out.println("Stop!!!");
}
}
class FireEngine extends Car {
void water() {
System.out.println("water!!");
}
}
class Ambulance extends Car {
void light() {
System.out.println("light!!");
}
}
FireEngine f = new FireEngine();
Car c = (Car)f; // 가능. 조상인 Car 타입으로 형변환
FireEngine f2 = (FireEngine)c; // 가능. 자손인 FireEngine타입으로 형변환
Ambulance a = (Ambulance)f; // 에러. 상속관계가 아닌 클래스 간의 형변환 불가
이건 객체 생성이 아니라 형변환을 대입해주는 것이다.
★ instanceof 연산자
- 참조변수의 형변환 가능여부 확인에 사용. 가능하면 true 반환
- 참조변수의 형변환은 조상과 자손만이 가능하다는것을 명심해야한다
- 형변환을 하기전에 반드시 instanceof로 확인 후에 진행한다.
class FireEngine extends Car
class Ambulance extends Car
이렇다고 가정할때
void doWork(Car c) {
if(c instanceof FireEngine) { 형변환을 확인한다.
FireEngine fe = (FireEngine)c; 형변환을 진행한다.
fe.water();
...
}
}
매개변수로 들어간 Car c는 Car의 자손인 FireEngine과 Ambulance도 가능하다.
이때 매개변수가 Ambulance라면 형제인 FireEngine은 형변환이 불가능하기 때문에 꼭 확인을 해야하는것이다
그러면 이런식으로 확인을 하는것이다.
FireEngine fe = new FireEngine();
System.out.println(fe instanceof Object) // true
System.out.println(fe instanceof Car) // true
System.out.println(fe instanceof FireEngine) // true
instanceof로 확인한 모두가 조상과 자손이기 때문에 형변환이 가능하다.
매개변수의 다향성
- 참조형 매개변수는 메소드 호출시, 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨 줄 수 있다.
class Product {
int price;
int bonusPoint;
}
class Tv extends Product {}
class Computer extends Product {}
class Audio extends Product {}
class Buyer {
int money = 1000;
int bonusPoint = 0;
void buy(Tv t) {
money -= t.price;
bonusPoint += t.bonusPoint
}
이런식으로 매개변수를 해놓으면 모든 물품 구매를 담당하는 중복 메소드를 만들어야한다.
}
그래서 매개변수에 애초에 다루고 있는 조상을 타입으로 넣는것이다.
void buy(Product p) {
money -= p.price;
bonusPoint += p.bonusPoint;
}
이렇게 되면 Product는 다형적 매개변수로 인해 자손의 모든 타입이 가능한것이다.
Buyer b = new Buyer();
Tv tv = new Tv();
Computer com = new Computer();
b.buy(tv);
b.buy(computer);
이런식으로 적어넣으면 한가지의 메소드로 다른 타입의 물건들을 타입으로 넣기만 하면 구매가 가능한것이다.
여러 종류의 객체를 배열로 다뤄보자
- 조상 타입의 배열에 자손들의 객체를 담을 수 있다.
Product p1 = new Tv(); Product p[] = new Product[3]
Product p2 = new Computer(); -----> p[0] = new Tv();
Product p3 = new Audio(); p[1] = new Computer();
p[2] = new 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) {
System.out.println("잔액이 부족합니다.");
return;
}
money -= p.price;
bonusPoint += p.bonusPoint;
Cart[i++] = p;
}
}
'Java > 객체 지향' 카테고리의 다른 글
호출 스택(call stack) (0) | 2023.05.08 |
---|---|
메소드(ft . return 문) (0) | 2023.05.08 |
변수의 종류 (0) | 2023.05.08 |
클래스와 객체(feat. 객체 지향 언어의 역사) (0) | 2023.05.04 |
클래스들의 관계. 상속과 포함 (0) | 2023.03.07 |