5.다형성 polymorphism
5.1 다형성이란
-여러가지 형태를 가질 수 있는 능력
-조상 타입 참조변수로 자손 타입 객체를 다루는 것
(조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있도록 하는 것)
class Tv{
boolean power;
int channel;
void power() { power= !power; }
void channelUp() { ++channel; }
void channelDown() { --channel; }
}
class CaptionTv extends Tv{
String text;
void caption() {/*생략*/ }
}
인스턴스 타입과 참조변수 타입이 일치하는것이 보통이지만 서로 상속관계에 있을 경우
조상 클래스 타입의 참조변수로 자손 클래스의 인스턴스를 참조하는것이 가능(타입불일치)
Tv t = new CaptionTv(); //조상타입의 참조변수로 자손 인스턴스를 참조
-객체와 참조변수의 타입이 일치할 떄와 일치하지 않을 때의 차이?
CaptionTv c = new CaptionTv(); //참조변수와 인스턴스의 타입 일치
Tv t = new CaptionTv(); //조상 타입 참조변수로 자손 타입 인스턴스 참조
-자손 타입의 참조변수로 조상 타입의 객체를 가질 수 없다.
Tv t = new SmartTv(); //ok Tv가 조상임
SmartTv s = new Tv(); //에러.허용안됨
실제 가지고 있는 멤버수보다 리모컨 개수가 많은건 안됨.
참조변수가 사용할 수 있는 멤버의 개수는 인스턴스의 멤버 개수보다 같거나 적어야 한다.
멤버수는 많은데 리모컨수가 적어서 리모컨 다 쓸 수 있는건 가능한거임
Q.참조변수의 타입은 인스턴스의 타입과 반드시 일치해야 하나?
A.아님. 일치하는 것이 보통 일반적이지만 일치 하지 않을 수 있다.
Q.참조변수가 조상타입일 때와 자손타입일 때의 차이?
A.참조변수로 사용할 수 있는 멤버의 갯수가 달라진다.
Q,자손 타입의 참조변수로 조상 타입의 객체를 가리킬 수 있나?
A.안됨
*조상타입의 참조변수로 자손타입의 인스턴스를 참조할 수 있다.
반대로 자손타입의 참조변수로 조상타입의 인스턴스를 참조할 수는 없다.
5.2참조변수의 형변환
-사용할 수 있는 멤버의 개수를 조절하는 것(리모컨을 변경)
(기본형의 형변환은 값이 바뀌지만 참조형은 주소값이 바뀌는거임)
-조상, 자손 관계의 참조변수는 서로 형변환 가능
자손타입 > 조상타입 : 형변환 생략가능
자손타입 < 조상타입 : 생략불가능
class Car { }
class FireEngine extends Car { }
class Ambulance extends Car { }
FireEngine f = new FireEngine(); //타입일치
Car c = (Car)f; //f를 c에 대입. 타입이 다르니까 형변환 써줘야함(자손>조상)
//5개를 가리키던 f를 c값에 넣어서 4개로 줄인거임
FireEngine f2 = (FireEngine)c; //조상>자손 (생략불가능)
//다시 리모컨변경해서 5개 사용가능
Ambulance a = (Ambulance)f; //상속관계가 아니라 형변환 불가능
class Ex {
public static void main(String asrgs[]) {
Car car = null;
FireEngine fe = new FireEngine();
FireEngine fe2 = null;
fe.water();
car = fe; //참조변수fe값을(주소값) car에 넣는거. 이제 참조변수 car도 fe와 같은 객체를 가리키게 됨
//car= (Car)fe; 에서 형변환이 생략된거임
// car.water(); car이 부를수 있는 거 4개임. 컴파일 에러 (fireengine꺼임)
fe2 = (FireEngine)car; //4개->5개로 증가 이기때문에 형변환 꼭 써줘야함
fe2.water();
}
}
//자식5개 조상4개. 줄어드는거는 안전한거임
class Car {
String color;
int door;
void drive(){
Syetem.out.println("drive, Brr-");
}
void stop() {
Syetem.out.println("Stop");
}
}
class FireEngine extends Car{
void water(){
Syetem.out.println("water!");
}
}
car = fe;
참조변수 fe가 참조하고 있는 인스턴스를 참조변수 car가 참조하도록 한다. fe의 값이 car에 저장 됨.
이때 두 참조변수 타입이 다르므로 참조변수 fe가 형변환되어야 하지만 생략 됨.
이제 참조변수 car을 통해서도 FireEngine인스턴스를 사용할 수 있지만, fe와 달리 car은 Car타입이므로 Car클래스의 멤버가 아닌 water()는 사용할 수 없다.
fe2 = (FireEngine)car;
참조변수 car가 참조하고 있는 인스턴스를 참조변수fe2가 참조하도록 함. 두 참조변수 타입이 다르므로 참조변수 car를 형변환 하였다. car와 달리 fe2는 FireEngine타입이므로 FireEngine인스턴스의 모든 멤버를 사용할 수 있다.
자손타입<=조상타입이라 형변환 생략불가능
형변환 할때 실제 인스턴스가 무엇인지가 중요함!
*조상타입의 인스턴스를 자손타입의 참조변수로 참조하는 것은 허용되지 않는다.
'JAVA' 카테고리의 다른 글
| JAVA | 재귀호출, 변수의 초기화 (0) | 2022.02.05 |
|---|---|
| JAVA | instanceof연산자, 매개변수 다형성, 객체 배열로 다루기 (0) | 2022.02.03 |
| JAVA | 오버라이딩, package, import, 제어자 (0) | 2022.01.26 |
| JAVA | 상속, 포함관계 (0) | 2022.01.24 |
| JAVA | 변수와 메서드, 오버로딩, 생성자 (0) | 2022.01.23 |