먼저.. 누가 이름을 지었는지는 모르겠지만, 내가 이해한 내용이 맞다면 왜 “타입 변환”이라고 지었는지.. 정말 궁금하다.
답을 아시는 분은 댓글에 너가 잘못 이해해놓고 누굴 탓하냐 이 바보야! 하신다거나.. 마자 나도 이 거 이상하더라 어이없지 참내 하고 공감하신다거나.. 해주시면 감사하겠삽니다 흑흑

자동 타입 변환

Child child = new Child();
Parent parent = child;
parent = child; // true

다음과 같은 코드가 있다고 생각해보자.
1행의 child는 Child타입이며, Child 객체이다.
2행의 parent는 Parent타입이며, Child 객체이다.
따라서 child와 parent는 다른 타입이지만, 모두 child 객체를 참조하고 있다.
(자동으로 타입 변환은 일어나지 않았다!)

자동 타입 변환 - 상속

상속일 때가 굉장히 흥미로운데, 아래와 같이 Child가 Parent클래스를 상속하고 있다고 가정해보자.

public class Parent {
	
	public void method1() {
		System.out.println("Parent-method1()");
	}
	public void method2() {
		System.out.println("Parent-method2()");
	}
}

public class Child extends Parent{
	
	@Override
	public void method2() {
		System.out.println("Child-method2()");
	}
	
	public void method3() {
		System.out.println("Child-method3()");
	}
}

public class ChildExample {
	public static void main(String[] args) {
		Child child = new Child();
		Parent parent = child;

		parent.method1(); // Parent-method1()
		parent.method2(); // Child-method2()
//		parent.method3(); // error
		
		child.method1(); // Parent-method1()
		child.method2(); // Child-method2()
		child.method3(); // Child-method3()

ChildExample에서 볼 수 있다시피, parent는 Parent타입이기 때문에 기본적으로 parent의 메소드를 불러올 수 있다. 하지만 child 객체를 지니고 있고, child에서 상속을 하며 method2()을 Overriding을 했기 때문에 Overriding 된 버전인 Child의 메소드를 불러올 수 있다. (상속만 하면 Parent 메소드 불러옴)

강제 타입 변환

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

앞서 자동 타입 변환한 parent 변수를 (Parent 타입, Child에 있는 객체) Casting해서 child 변수(Child 타입, Parent를 Casting하여 Child에 있는 객체)를 만드는 것이다. 본래 자연스러운 타입 변환은 자식이 부모의 타입을 따라가는 것인데, 이 경우 부모의 타입을 자식 타입으로 강등시키는 것이기 때문에 강제 타입 변환을 시키는 Casting과정이 필요하다. 그리고 이 과정을 통해서 child 변수는 Child에 있는 메소드를 쓸 수 있게 된다.

여기에서 궁금해지는 건, 2행의 parent 변수는 이제 뭘 불러올 수 있는지다. Casting되었으니, 이 친구에게도 뭔가 변화가 있지 않을까? 아래 예제를 참조해보자.

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;
	
	@Override
	public void method2() {
		System.out.println("Child-method2()");
	}
	
	public void method3() {
		System.out.println("Child-method3()");
	}
}

public class ChildExample {
	public static void main(String[] args) {
		Parent parent = new Child();
		
		parent.field1 = "data1"; 
//		parent.field2 = "data2"; // error
		parent.method1(); // Parent-method1()
		parent.method2(); // Child-method2()
//		parent.method3(); // error
		
		System.out.println("------------------");
		
		Child child = (Child)parent; 
		
		child.field1 = "data1";
		child.field2 = "data2";
		child.method1(); // Parent-method1()
		child.method2(); // Child-method2()
		child.method3(); // Child-method3()

		System.out.println("------------------");
		
		parent.field1 = "data1";
//		parent.field2 = "data2"; // error
		parent.method1(); // Parent-method1()
		parent.method2(); // Child-method2()
//		parent.method3(); // error
	}
}

parent는 그대로 Parent타입 child 객체를 지녔다.
ㅎㅎ..

결론

자동 타입 변환이라고 불리우는 건 실제로 어떠한 변수의 타입이 변환되는 것이 아니라, 부모 타입 객체가 자식 객체를 참조하게 된다는 걸 의미한다. 그렇지만 여전히 부모 타입 객체는 부모 타입을 유지한다.
자동 타입 변환에서 가장 중요한 건 자식이 부모를 상속받을 때, 부모 객체는 부모 클래스에 존재하는 메소드만 접근가능하지만, 자식 클래스에서 Overriding한 메소드가 있다면, 자식 클래스에서 Overriding한 그 메소드를 사용하게 된다.
자동 타입 변환은 다형성에서 잘 설명되는데, 즉 “자식이 부모를 상속받고 있으면, 부모 타입인 곳에 자식을 써도 된다.” 정도로 이해하면 된다.

강제 타입 변환은 자동 타입 변환한 부모 변수(부모 타입, 자식 객체)를 Casting하여 자식 타입의 자식 변수에 저장하는 것으로, 자식 변수는 자식 타입에 자식 객체를 가지게 된다.




참조

이것이 자바다 책

profile
불타오르는 진루나

0개의 댓글