본문 바로가기
JAVA

JAVA | 다형성, 참조변수의 형변환

by 개발송이 2022. 1. 28.

 

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인스턴스의 모든 멤버를 사용할 수 있다.

자손타입<=조상타입이라 형변환 생략불가능

 

 

형변환 할때 실제 인스턴스가 무엇인지가 중요함!

 

*조상타입의 인스턴스를 자손타입의 참조변수로 참조하는 것은 허용되지 않는다.