본문 바로가기

자바스프링웹공부(2024)/자바

2024.09.13. ref casting 참조형변환

반응형

*  레퍼런스 형변환

- 참조형(레퍼런스타입) 끼리의 형변환 (상속 관계에서만 사용 가능)
- 참조형 변수를 사용하여 다른 타입의 인스턴스(객체)를 참조하기 위해 변환하는 것.
- 업캐스팅(Up casting)과 다운캐스팅(Down casting)으로 분류됨
 
1. 참조데이터타입에서의 묵시적(자동) 형변환 = 업캐스팅
2. 참조데이터타입에서의 명시적(자동) 형변환 = 다운캐스팅
    => 이전에 이미 업캐스팅 된 인스턴스를 다시 다운캐스팅 하는 경우

 

 

* 클래스들의 관계 (Has - a, Is - a)

1. Has-a (포함관계)
- 어떤 객체가 다른 객체에 포함되는 관계
- 대부분의 클래스들의 관계는 Has-a 관계가 적용됨
- 자동차 has a 타이어, 스마트폰 has a 스피커, 영웅 has a 무기 

1)집합관계 : 필수아님
- 객체가 다른 객체에 포함될 때 해당 객체가 없어도 동작에 문제가 없는 관계
   => 객체 상호간의 라이프 사이클이 다른 관계
 ex. 자동차 has a 라디오
      컴퓨터 has a 스피커
      영웅  has a 무기
2)구성관계 : 필수!
- 객체가 다른 객체에 포함될 때 해당 객체 없이는 동작이 불가능한 관계
   => 객체 상호간의 라이프 사이클이 동일한 관계
    ex. 자동차 has a 엔진, 컴퓨터 has a CPU

2. Is-a 관계(상속 관계)
- 비슷한 속성 및 동작을 갖는 객체 사이의 관계
ex. 초등학생, 중학생, 고등학생 객체들의 공통점은 학생
  => 이때, 학생은 초등학생, 중학생, 고등학생의 상위개념이므로 모두를 포함함
  => 초등학생 is a 학생 => 학생의 모든 구성요소는 초등학생이 갖고 있음
      스마트폰 is a 핸드폰 => 핸드폰의 모든 구성요소는 스마트폰이 갖고 있음
     
     * 반대는 안됨.
       학생 is a 초등학생 (X)
       동물 is a 강아지 (X)

- Is-a 관계가 성립하는 경우 좌변의 객체는 우변의 객체를 상속받아 정의한 객체 성립
- Is-a 관계를 판별하는데 사용하는 연산자 : instanceof 연산자

3. instanceof 연산자
- 좌변의 객체(참조변수)가 우변(클래스) 타입인지 판별하는 연산자
- 판별 결과는 boolean타입으로 리턴되며, 결과값이 true이면 형변환 가능한 관계
    (=> 업캐스팅 도는 다운캐스팅 모두 ture가 리턴됨)

 

<기본문법>
if(a instanceof B) {// => a는 참조변수, B는 클래스 또는 인터페이스)
      // a is a B가 성립할때 실행할 코드들.
}


package ref_casting;
public class Ex2 {
	public static void main(String[] args) {
		SmartPhone2 sp = new SmartPhone2("010-1234-5678", "안드로이드");
		// sp는 SmartPhone입니까?? true
		if (sp instanceof SmartPhone2) {
			System.out.println("sp는 SmartPhone입니다");
		} else {
			System.out.println("sp는 SmartPhone이 아닙니다");
		}
		System.out.println("----------------------------------------------------------------------------------------");
		//spㅍ는 HandPhone2입니까?? true
		if (sp instanceof HandPhone2) {
			System.out.println("sp는 HandPhone2입니다");
		} else {
			System.out.println("sp는 HandPhone2이 아닙니다");
		}
		System.out.println("----------------------------------------------------------------------------------------");
		// hp는 SmartPhone입니까?  false
		HandPhone2 hp = new HandPhone2("010-1111-2222");
		if (hp instanceof SmartPhone2) {
			System.out.println("hp는 SmartPhone입니다");
		} else {
			System.out.println("hp는 SmartPhone이 아닙니다");
		}
		System.out.println("----------------------------------------------------------------------------------------");
		HandPhone2 hp2 = new SmartPhone2("010-1234-5678", "안드로이드");
		// hp2는 SmartPhone입니까??  false
		if (hp2 instanceof SmartPhone2) {
			System.out.println("hp는 SmartPhone입니다");
			SmartPhone2 sp2 = (SmartPhone2)hp2;
			sp2.call();
			sp2.sms();
			sp2.kakaoTalk();
			
		} else {
			System.out.println("hp는 SmartPhone이 아닙니다");
		}
		
		System.out.println("----------------------------------------------------------------------------------------");
		// hp2는 SmartPhone입니까??  false
		if (hp2 instanceof HandPhone2) {
			System.out.println("hp2는 HandPhone2입니다");
		} else {
			System.out.println("hp2는 HandPhone2이 아닙니다");
		}
	}
}
class HandPhone2 {
	String number;
	// 번호없는 폰은 만들기 싫어서 기본 생성자 없앰!!
	public HandPhone2(String number) {
		this.number = number;
	}
	public void call() {
		System.out.println("전화기능");
	}
	public void sms() {
		System.out.println("문자기능");
	}
}
class SmartPhone2 extends HandPhone2 {
	String osName;
	public SmartPhone2(String number, String osName) {
		super(number);
		this.osName = osName;
	}
	public void kakaoTalk() {
		System.out.println("카카오톡");
	}
}

 

class Phone {
	public void call() {
		System.out.println("전화걸기!");
	}
}
class HandPhone extends Phone {
	public void sms() {
		System.out.println("문자 기능");
	}
}
class SmartPhone extends HandPhone {
	public void kakaoTalk() {
		System.out.println("카톡 메시지 전송");
	}
}
public class Test1 {
	public static void main(String[] args) {
		Phone 전화기 = new Phone();
		HandPhone 핸드폰 = new HandPhone();
		SmartPhone 스마트폰 = new SmartPhone();
		
		Phone 할아버지;	// 전화만
		HandPhone 아버지;	// 전화랑 문자만
		SmartPhone 나;	// 전부
		
		// 업캐스팅을 해보자.
		할아버지 = 스마트폰;
		할아버지.call();
		
		아버지 = 스마트폰;
		아버지.sms();
		
		// 되는 다운캐스팅을 해보자.
		Phone 할아버지1 = new HandPhone();
		HandPhone 아버지1;
		아버지1 = (HandPhone)할아버지1;
		아버지1.call();
		아버지1.sms();
		
		Phone 할아버지2= new SmartPhone();
		SmartPhone 나1;
		나 = (SmartPhone)할아버지;
		나.call();
		나.kakaoTalk();
	}
}

 

A a = (A)new D(); // 생성자니까 생성자에 있는 ABD 찍힘.
B b = (B)a; // b : a,b 담김. 생성자는 없고, Aa(), Bb() 찍을 수 있따.
A a1 = b;	// Aa() 만 찍을 수 있음. ==> 자식은 찍을 수가 없다. 왼쪽 기준으로 왼쪽 까지만 찍을 수 있따.
C c = (C)a1; // down casting.은 바로 생성하는 거 배고는 안된다고 봐야함. 위에 a는 담을 수 있는 이유가 new로 생성했기 때문이다.
-------------------------------------
A a = new F();
C c = (C)a; // down cast - a,c 담을 수 있다. 생성자느 ㄴ없음
H h = (H)a; // down cast - 에러. h는 F의 자식이다. h가 f보다 조상이 아니므로 에러가 난다. 
/*
 	다운캐스팅일 때 되는 것 
    1. new 해서 바로 생성자를 담을 때 
    2. 위에서 만든 생성자의 변수를 담을 때
	단, 담는 변수가 오른쪽의 실제 담긴 값보다 조상이어야 한다. 
*/
반응형