캐스팅이란?
캐스팅이란 타입을 변환하는 것이고, 형변환이라고도 한다.
자바의 상속관계에 있는 클래스 간에는 서로 형변환이 가능한데, 이 때 상황에 따라 업캐스팅과 다운캐스팅으로 나뉘어진다.
업캐스팅(Upcasting)
업캐스팅은 자식 클래스의 객체가 부모 클래스타입으로 형변환 되는 것을 말한다.
아래 코드를 확인해보자.
class Person {
public String name;
public Person(String name) {
this.name = name;
}
}
class Student extends Person{
public int id;
public Student(String name) {
super(name);
}
}
public static void main(String[] args) {
Student student = new Student("홍길동");
Person person = student;
person.name = "부모 이름";
person.id // 컴파일 오류
}
위의 코드에서 부모 클래스는 Person이고 자식 클래스는 Student이다.
Person person = student가 업캐스팅을 한 부분이다.
person이 Student 객체를 가리키지만, person은 Person 타입이기 때문에 Person 클래스의 멤버에만 접근이 가능하다. (id에 접근 불가)
사용 이유
위의 글을 읽다보면 "어차피 자식 클래스의 멤버에는 접근도 못하는데, 뭐하러 있는거지?" 라는 의문이 들 수도 있다.
이것의 해답은 "다형성(Polymorphism)"과 관련있다.
다음 예제를 보자.
class Developer{
public String name;
public void developApp(){
// 서비스 개발
}
}
class IosDeveloper extends Developer{
@Override
public void developApp(){
// IOS 개발
}
}
class AndroidDeveloper extends Developer{
@Override
public void developApp(){
// Android 개발
}
}
public class Company {
public void developService(Developer developer){
developer.developApp();
}
}
public class UpCasting {
public static void main(String[] args) {
Company company = new Company();
Developer developer = new AndroidDeveloper();
company.developService(developer);
}
}
이 코드에서 업캐스팅을 사용하지 않고 각 개발자들의 메서드를 호출한다면?
public void developService(Developer developer){
// developer.developApp();
if(developer instanceof IosDeveloper){
// ios 개발
} else if(developer instanceof AndroidDeveloper){
// Android 개발
}
}
이처럼 조건문이 추가되어야 할 것이다.
업캐스팅은 다형성과 관련이 있으며, 위 예제에서 서비스 개발을 할 때 IOS인지 Android인지에 상관없이 개발자만 넘겨주면 Company는 타입을 검사하지 않고 쓰면 된다.
다운캐스팅(Downcasting)
업캐스팅 된 것을 복구하는 것을 다운캐스팅이라고 한다.
하위 클래스로의 다운캐스팅을 할 때는 타입을 명시해줘야한다.
아래 코드를 보자.
public class Downcasting {
public static void main(String[] args) {
Person person = new Student("홍길동");
Student student = (Student) person;
student.id = 1;
student.name = "학생";
}
}
class Person {
String name;
public Person(String name) {
this.name = name;
}
}
class Student extends Person{
int id;
public Student(String name) {
super(name);
}
}
위에서 말한 바와 같이 업캐스팅과 다른점은 명시적으로 타입을 지정해야한다는 것이다.
그리고 다운캐스팅은 업캐스팅이 된 것을 복구하는 것이기 때문에 업캐스팅이 선행되어야 한다.
무분별한 다운캐스팅은 컴파일 시점에는 괜찮지만 런타임오류를 발생시킬 수 있다.
직관적인 예제라 이해가 잘되네요.