자바의 기본형 변수를 다루면서 형변환(캐스팅)을 다뤘습니다. 어느 한 타입을 다른 타입으로 변경하는 것을 형변환
이라고 했는데요. 마찬가지로 객체도 참조형 변수이기 때문에 형변환이 가능합니다. 단, 객체에서는 서로 상속 관계에 있는 객체들만이 형변환을 할 수 있습니다.
객체에서도 마찬가지로 자동 형변환과 강제 형변환이 수행될 수 있습니다.
객체에서의 자동 형변환은 자식 타입(클래스)의 객체에서 부모 타입으로 형변환을 할 때 발생합니다. 기존의 기본형에서 작은 타입에서 큰 타입 변환은 자동으로 수행되었듯이 자식 클래스에는 부모 클래스의 멤버들을 포함하고 있기 때문에 자식 클래스는 부모 클래스로 취급할 수 있어 자동적으로 형변환이 일어날 수 있습니다.
정리하자면
자식 타입 -> 부모 타입
은 자동 형변환이 가능합니다.
예를들면, 사과는 과일의 속성과 기능을 물려받았으므로 사과는 과일이라고 말할 수 있습니다. 따라서 다음과 같이 부모 타입 객체에 자식 타입 객체를 넣을 수 있으며 이때 자동 형변환이 일어납니다.
public class Fruit {
protected String color;
protected int price;
protected Fruit() {}
public void parentMethod() {
System.out.println("부모 객체 메소드 호출");
}
}
public class Apple extends Fruit {
public Apple(String color, int price) {
this.color = color;
this.price = price;
}
public void childMethod() {
System.out.println("자식 객체 메소드 호출");
}
}
public class Main {
public static void main(String[] args) {
Fruit fruit = new Apple("Red", 4000);
/*
* 또는
* Apple apple = new Apple("Red", 4000);
* Fruit fruit = apple;
* 위와 같은 코드도 성립
*/
fruit.parentMethod();
fruit.childMethod();
}
}
자식 타입으로 선언했지만, 부모 타입으로 형변환했기 때문에 부모 객체의 메소드에만 접근할 수 있고 자식 객체의 메소드에 접근하려고하면 오류가 발생합니다.
지금은 부모-자식 관계만 언급했지만, 계층 구조에서 조상-자손 관계에 있기만 하다면 자동 형변환이 가능합니다.
반대로 자식 타입 객체은 부모 타입 객체보다 더 많은 속성과 기능을 가지고 있기 때문에 부모 타입은 자식 타입으로의 자동 형변환이 발생하지 않습니다. 이런경우엔 강제 형변환
을 사용해야하는데 객체의 강제 형변환에는 조건이 있습니다.
아무때나 부모 타입을 자식 타입으로 변환할 수는 없고, 부모 타입으로 자동 형변환된 자식 타입에 대해서만 강제 형변환을 사용할 수 있습니다. 마찬가지로 캐스팅 연산자(타입)
을 이용해서 강제 형변환을 수행합니다.
정리하면,
강제 형변환
은 자동 형변환이 수행된 객체만 사용이 가능합니다. (자식 타입이 부모 타입으로 변환 된 객체에만 사용 가능)
public class Main {
public static void main(String[] args) {
Fruit fruit = new Apple("Red", 4000); //자동 형변환
fruit.parentMethod();
Apple apple = (Apple) fruit; //강제 형변환
apple.childMethod();
}
}
한 번 부모 메소드로 자동 형변환된 fruit 객체를 자동 형변환을 통해 자식 객체 타입인 Apple로 강제 형변환을 통해 타입을 바꿔주었고, 오류없이 자식 객체 메소드에 접근할 수 있게 되었습니다.
선언이 다르지만, apple에 fruit를 형변환해서 저장했기 때문에 내부적으로 apple과 fruit는 같은 객체를 가리킵니다.
System.out.println(apple == fruit);