[Java]/Program source (java)

★★★ 116 - Java 클래스 고급 : 상속 클래스 간의 업 캐스팅, 다운 캐스팅

Jelly-fish 2023. 9. 13. 17:50

( 부모 참조 변수 ← 자식 객체 : 업 캐스팅 ), 업 캐스팅을 한번 한 후(자식에서 부모로 승격)에만 다운 캐스팅 가능!!

 

/*=======================================
  ■■■ 클래스 고급 ■■■
  - 상속 관계에 있는 클래스들 간의 캐스팅
    (업 캐스팅, 다운 캐스팅)★☆★
=========================================*/

// super class, 부모 클래스, 상위 클래스
class SuperTest116
{
	public int a = 10, b = 20;

	public void write()
	{
		System.out.println("슈퍼클래스 write() 메소드...");
	}

	public int hap()
	{
		return a + b;
	}
}



// sub class, 자식 클래스, 하위 클래스
class SubTest116 extends SuperTest116
{
	public int b=100, c=200;

	@Override
	public int hap()
	{
		return a + b + c;
	}

	public void print()
	{
		System.out.println("서브클래스 print() 메소드...");
	}
}


// main() 메소드를 포함하는 외부의 다른 클래스
public class Test116
{
	public static void main(String[] args)
	{
		// 하위 클래스 기반 인스턴스 생성
		SubTest116 ob1 = new SubTest116();
		// 자식이 인스턴스에 올라가면, 부모의 인스턴스 메모리도 같이 올라간다!!!!

		System.out.println("ob1.b : " + ob1.b);
		//--==>> ob1.b : 100


		// ○ 업 캐스팅
		// 자식 객체에 부모의 인스턴스까지 메모리에 저장되어 있기 때문에 
		// 자식 클래스 객체 ob1을 부모 클래스 타입으로 형변환 할 수 있는 것이다.
		
		SuperTest116 ob2 = ob1;	// 상위 타입으로 가는 캐스팅(형변환)이다.
		//-- 『SuperTest116 ob2 = (SuperTest116)ob1;』 과 동일한 코드
		/*
		
		학생 혜인이 = new 학생();
		
		포유류 사람 = 혜인이;		// 『포유류 사람 = (사람)혜인이;』와 동일한 코드

		※ 학생도 포유류~!!!

		class 포유류		class 학생 extends 포유류
		{					{
		}					}


		*/
		
		System.out.println("ob2.b : " + ob2.b);
		//System.out.println("ob2.b : " + ((SuperTest116)ob1).b);
		//--==>> ob2.b : 20
		//-- 메모리 그림판에서 변수는 객체별로 따로 할당되기 때문에
		//   변수 b 는 ob2 의 변수이다.

		
		// ob2 는 ob1으로 태어났는데... 자식 때 메소드를 튜닝했기 때문에...!!! 돌아갈 수 없다!

		// 인스턴스 생성 -> 클래스 전체가 메모리에 올라가는 것이 아니라
		//                  클래스가 갖고 있는 멤버 변수만 올라간다.
		//                  메소드의 경우 다른 메모리(method 영역) 에 저장이 된다.

		System.out.println("합   : " + ob2.hap());
		//--==>> 합   : 310
		//-- hap() 메소드는 오버라이딩(Overriding) 되어 있고
		//   ob2 는 ob1을 업 캐스팅한 상태의 객체이므로
		//   『SuperTest116』의 hap() 메소드를 호출하는 것이 아니라
		//   『SubTest116』에서 재정의한 hap() 메소드를 호출하게 된다.
		//   즉, 메소드는
		//   업 캐스팅이 되더라도
		//   재정의(덮어쓰기)한 이상... 원래의 기능으로 되돌릴 수 있다.


		ob2.write();
		//--==>> 슈퍼클래스 write() 메소드...

		//ob2.print();
		//--==>> 에러 발생(컴파일 에러)
		// 자식은 부모 것을 마음대로 쓸 수 있지만, 부모는 자식 것을 마음대로 쓸 수 없다!

		// ○ 다운 캐스팅
		((SubTest116)ob2).print();
		//--==>> 서브클래스 print() 메소드...


		// ※ 추가 관찰 ------------------------------------------------------------------
		//    다운 캐스팅 가능 여부
		

		// 상위 클래스 기반 인스턴스 생성
		SuperTest116 ob3 = new SuperTest116();
		// 부모 객체는 인스턴스 생성할 때 자식 객체가 메모리에 올라가지 않는다!!!

		SubTest116 ob4;

		//System.out.println(ob3.c);
		//--==>> 에러 발생(컴파일 에러)
		//-- 상위 객체는 하위 객체의 멤버에 접근하는 것이 불가능하다.
		//   (상위 객체 입장에서는 어떤 하위 객체가 존재하는지도 알 수 없음)

		//ob4 = ob3;
		//--==>> 에러 발생(컴파일 에러)
		//-- 상위 객체는 하위 객체에 담을 수(참조할 수) 없다.

		
		
		// 만약, 부모 클래스의 인스턴스를 생성할 때 자식 객체의 메모리까지 함께 올라간다면...
		// 자식 클래스가 여러 개 있을 때 수많은 메모리를 할당 받아야 한다... (불가능)

		// ↓ 부모 클래스를 객체 생성할 때는, 메모리에 자식 객체의 메모리까지 함께 올라가지 않기 때문이다!!
		ob4 = (SubTest116)ob3;
		//--==>> 에러 발생(런타임 에러) ClassCastException
		//-- 작성된 구문의 무법적인 구조만 봤을 때...
		//   이 구문은 다운 캐스팅이 이루어지는 상황이다.
		//   하지만, 정상적인 캐스팅이 이루어지지 않는다.
		//   현재 SubTest116 객체에 대한 메모리 할당은 이루어지지 않은 상태이기 때문이다.
		//   그러므로 이 상황에서 다운 캐스팅은 불가능하다.



	}
}