본문 바로가기

Programming/JAVA

상속(10) - 강제 타입 변환(Casting)

java

 

 

 

우리가 앞선 과정에서 부모 클래스를 상속받는 자식 클래스와 관련하여, [자동 타입 변환]에 대해서 학습했습니다. 요약하면, 주요 원칙은 '자식 클래스는 부모 클래스 타입으로 사용될 수 있다'였죠? 이는 필드에서 인스턴스로 사용될 때 혹은 파라미터 일 경우에도 적용하였습니다. 

 

다시 한번 노파심에 짚고 넘어가자면, 자식 클래스는 기본적으로 부모 클래스의 모든 필드와 메서드 요소를 그대로 가지고 있으며(또는 오버라이드로 메서드 재정의) 여기에 자식 클래스 고유의 요소들을 갖고 있기 때문에 부모 클래스로 자동 타입 변환이 되더라도 사용에 지장이 없습니다. 

 

Parent parent = new Child();

 

 

자, 여기서 '자동' 타입 변환에 대해서 말했으면 자동이 아닌 것도 있겠죠? 맞습니다. 이는 [강제 타입 변환]을 하는 경우이며 이를 캐스팅(Casting)으로 표현합니다. 그럼 자식 클래스 → 부모 클래스의 경우 이외에 어떤 때에 이 캐스팅이 발생하는지 살펴보겠습니다. 

 

 


 

 

자식 클래스가 부모 클래스 타입의 데이터에 대입될 때, 자동 타입 변환이 발생했습니다. 그러면, 알다시피 자식 클래스에만 선언된 메서드는 사용할 수 없습니다. 그런데, 정말 피치 못할 사정으로 해당 자식 클래스에서 정의된 메서드를 꼭 써야 하는 상황이 발생했습니다. 설명했다시피, 부모 클래스 타입으로 자동 변환된 경우에는 사용할 수 없죠?

 

이런 경우를 위해서, 강제 타입 변환(Casting)이 존재합니다. 자식 클래스 타입이 부모 클래스 타입으로 자동 변환이 일어난 상태에서, 다시 자식 클래스 타입으로 변환하는 경우에만 강제로 타입을 변경할 수 있습니다(자식 클래스 타입이 부모 타입 클래스인 척 가면을 쓰고 있었으니까, 그 변장을 벗어 버릴 수 있는 것이죠).

 

// 자동 타입 변환
Parent parent = new Child();

// 강제 타입 변환
Child child = (Child) parent;

 

그럼 아래와 같이 간단한 예제를 통해서, 부모 클래스 타입으로 자동 변환된 자식 클래스 타입의 인스턴스를 사용하는 사례를 살펴보도록 하겠습니다. 

 

 


 

 

public class Parent {
	public String field1;
	
	public void method1() {
		System.out.println("Parent_method1()");
	}
	
	public void method2() {
		System.out.println("Parent_method2()");
	}
}

 

public class Child extends Parent {
	public String field2;
	
	public void method3() {
		System.out.println("Child_method3()");
	}
}

 

public class ExampleMain {	
	public static void main(String[] args) {
		Parent parent = new Child();
		
		parent.field1 = "EXAMPLE1";
		parent.method1();
		parent.method2();
		
		System.out.println(parent.field1);
		
		// parent.field2 = "EXAMPLE2";
		// parent.method3();
		
		Child child = (Child) parent;
		child.field2 = "EXAMPLE2";
		child.method3();
		
		child.field1 = "NEW_EXAMPLE";
		System.out.println(parent.field1);
	}
}

/* 출력
Parent_method1()
Parent_method2()
EXAMPLE1
Child_method3()
NEW_EXAMPLE
*/

 

위의 케이스를 보게 되면, 위에서 설명한 것처럼 parent라는 객체 변수는 사실 Child 클래스 타입인데 자동 타입 변환이 이루어졌습니다. 그래서 원래 Child 클래스 타입임에도 불구하고 field2와 method3( )를 사용할 수 없죠.

 

그래서 parent 변수를 강제 객체 변환하여 Child 클래스 타입 변수에 대입하였습니다. 이때, child를 사용해 field2와 method3( )를 사용할 수 있게 되었습니다. 

 

중요한 것은, 이미 heap 영역에서 참조되고 있는 parent 변수를 child라는 변수로 '타입만 강제 변환'한 상태이기 때문에, child.field1의 값을 "NEW_EXAMPLE"로 바꾸었을 때, parent.field1을 출력하면 이 값 역시 "NEW_EXAMPLE"로 바뀌어 있습니다. 이를 통해 변수 스택 영역의 child와 parent라는 변수는 힙 영역의 동일한 인스턴스를 참조하고 있는 변수라는 것도 확인할 수 있습니다.