
업캐스팅(upcasting)과 다운캐스팅(downcasting)을 이해해보자!
요즘 시험기간이라 업캐스팅, 다운캐스팅을 공부하고 있는데 이해가 도저히 안 되는 거에요,,
그래서 제가 이해하고자, 또 다른 사람들에게 더 쉽게 알려주고자 업캐스팅과 다운캐스팅에 관련하여 글을 쓰려 합니다!
업캐스팅과 다운캐스팅 모두에 들어있는 바로 이 Casting은 무엇일까요?
캐스팅은 데이터 타입이 다른 경우에 하나의 데이터 타입으로 통일해주기 위해 사용합니다.
정수와 실수를 더하려면 두 변수의 데이터 타입이 같아야 하는 경우에 사용이 되겠죠?
캐스팅에는 총 두 가지의 종류가 있습니다.
프로그래머의 명시적인 요청 없이 컴파일러가 자동으로 타입을 변환하는 것
자동형변환이 일어나는 경우에는 작은 범위의 데이터타입에서 큰 범위의 데이터 타입으로 변환하는 경우에 발생하게 됩니다.
int i = 10;
double d = 3.14;
double result = d + i; // i가 자동으로 실수형으로 변환됨
위와 같이 int타입을 double타입으로 변환할 때 자동적으로 사용되겠죠.
프로그래머가 직접 타입을 변환하는 것
명시적형변환은 큰 범위의 데이터타입을 작은 범위의 데이터타입으로 강제적으로 형변환할 때 사용하게 됩니다.
자신보다 작은 곳에 자신을 맞춰야 하므로 손실이 생길 수 있으며, 꼭 ()를 사용하여 강제형변환을 할 타입을 적어주어야 합니다.
int i = 10;
double d = (double)i;
이후 우리가 알아볼 업캐스팅은 자동형변환에 해당하고, 다운캐스팅은 명시적형변환에 해당합니다.
그렇다면 업캐스팅은 과연 무엇일까요?
업캐스팅(upcasting)이란? 서브 클래스 객체를 슈퍼 클래스 타입으로 타입 변환하는 것
서브 클래스 객체를 슈퍼 클래스 타입으로 타입 변환을 한다는 것에서 우리는 업캐스팅과 다운캐스팅은 상속 관계에서만 이루어진다는 것을 유추할 수 있겠죠?
솔직히 이론으로는 잘 와닿지 않을 것입니다. 바로 예제를 볼까요?

부모클래스인 Person과 Person클래스를 상속받은 자식클래스인 Student클래스가 있습니다.
main에서 Person p가 생성이 되었죠? 이 때는 객체가 생성되지 않고 그저 p라는 이름의 껍데기만 만들어진 상태입니다.
바로 다음에 자식클래스인 Student s = new Student("이재문");의 형태로 객체가 생성이 되었습니다.
이 때, Student는 Person클래스를 상속받았기 때문에
위의 모든 멤버변수와 메서드를 바라보며 접근할 수 있습니다.
그 다음을 볼까요? 드디어 업캐스팅이 이루어졌습니다.
Person p;
Student s = new Student("이재문");
p = s;
위의 코드는 아래와 같습니다.
Person p;
Student s;
p = new Student("이재문");
s가 업캐스팅이 되었습니다. 우리는 이것을 s를 p로 부른다. 라고 칭하겠습니다.
자식클래스를 슈퍼클래스로 부른다. 라고도 말할 수 있겠군요.
자동차와 전기차가 그 예시입니다.
자동차를 부모클래스라고, 전기차를 자식클래스라고 칭해봅시다.
우리는 전기차를 볼 때 "전기차다!" 라고 할 수도 있지만 "자동차다!"라고 말할 수도 있습니다.
하지만 아무 자동차나 보고서 "전기차다!" 라고 말을 할 수는 없겠죠? 자동차 중에서는 전기차도 있지만 전기차가 아닌 차도 많으니까요.
따라서 p = s를 통해 우리는 전기차를 자동차라고 부를 수 있는 것입니다.
이렇게 전기차를 자동차로 업캐스팅시켰을 때, 볼 수 있는, 즉 접근할 수 있는 멤버변수와 메서드는 자동차인 Person클래스 안의 멤버와 메서드밖에 없습니다.
우리는 전기차가 아닌 자동차의 시선으로 바라보고 있기 때문에 Student클래스가 바라보는 것이 아닌 Person클래스가 바라보는 것만을 접근할 수 있는 것입니다.
밑의 컴파일 오류가 나는 부분을 볼까요?

p객체는 지금 s객체입니다. 하지만 Person타입으로 업캐스팅이 된 상태이므로 사실상 Person클래스가 접근할 수 있는 것들인 name id Person(String name)만 사용할 수 있습니다.
그래서 Person클래스 안에는 name멤버변수는 있지만 grade와 department는 p가 볼 수 없는 Student클래스에 있기 때문에 접근하지 못해 오류가 나는 것입니다.
- 업캐스팅은 자동형변환(형변환)에 해당한다.
- 업캐스팅과 다운캐스팅은 상속관계에서만 이루어질 수 있다.
s를Person타입으로 업캐스팅시키면s객체는Person이 바라보는 것들만을 접근할 수 있다.
위의 업캐스팅을 이해했다면 다운캐스팅은 훨씬 쉽습니다.
슈퍼클래스 객체를 서브클래스 타입으로 변환하는 것
쉽게 말해 업캐스팅으로 인해 서브클래스 객체가 슈퍼클래스 타입이 된 것을 원래대로 되돌려 놓는다는 얘기입니다.
좁아진 시선을 다시 원래대로 넓힌다고 말할 수도 있겠네요.
앞에서 다운캐스팅은 명시적형변환이라고 말했던 기억이 나시나요?
명시적형변환을 할 때에는 타입 변환 표시를 꼭 해주어야 했듯, 다운캐스팅을 할 때에도 자식클래스의 타입을 반드시 명시해주어야 합니다.
class Person {..}
class Student extends Person {...}
...
Person p = new Student("이재문"); // 업캐스팅
...
Student s = (Student)p; // 다운캐스팅
더 정확한 이해를 위해 다운캐스팅 예시를 함께 봅시다.

위의 사진에서
Person p = new Student("이재문");
으로 업캐스팅이 되었죠? 그렇다면 p는 Student객체지만 Person클래스가 볼 수 있는 name id Person()만 접근하여 사용할 수 있을 것입니다.
그 다음 새로운 Student객체인 s가 선언이 되고,
그 이후에 Student객체이며 Person타입인 p를 (Student)p로 인해 다시 Student타입으로 변환하는 다운캐스팅이 일어납니다.
이러한 다운캐스팅을 통해 다시 p는 Student타입이 되며 grade department Student()도 함께 접근하여 사용할 수 있게 됩니다.
Student타입인 것과 Student객체인 것은 엄연히 구분되어야 합니다. "타입"과 "객체"에 주의하며 다시 정독해보세요!
주의할 점입니다! 다운캐스팅은 반드시 업캐스팅이 된 객체에만 가능합니다.
업캐스팅이 되지 않은 부모객체에 다운캐스팅을 시도하는 것은 생각해보면 당연히 안 되는 것입니다.
원래 상속관계에서는 부모클래스가 자식클래스에 접근할 수 없는데 부모클래스를 다운캐스팅하는 행위는 이가 가능하도록 만들어줄 수 있기 때문이죠.
단순히 업(UP)을 해주었으니 다시 다운(DOWN)을 해주는 것이라고 생각하면 더 이해가 쉬우실 겁니다.
💡( 참고 ) 업캐스팅이 되지 않은 객체에 다운캐스팅을 시도하면 각각의 실행과 컴파일이 될까요??
정답은 컴파일은 되지만 실행은 되지 않습니다.
그럼 다시 예제 사진으로 넘어가서 오류가 나는지 안 나는지를 볼까요?

s.name을 출력하면 이재문이라는 이름이 잘 출력이 될 것입니다.
이것은 p를 다운캐스팅하지 않아도 접근이 가능했던 부분입니다.
s.grade = "A";부분 또한 오류가 나지 않습니다.
이는 p를 다운캐스팅한 것을 s에 저장하여 Student타입이 되었기 때문에 grade에 접근이 가능해진 덕분입니다.
- 다운캐스팅은 명시적형변환에 해당하여 형변환하는 자식클래스의 타입을 명시해주어야 한다.
- "타입"인 것과 "객체"인 것은 다르다. 부모클래스 타입인데 자식클래스 객체이면 업캐스팅이 된 것이라고 한다.
- 다운캐스팅은 업캐스팅이 된 객체에만 가능하다. 이는 실행때 오류가 나게 된다.
업캐스팅과 다운캐스팅을 이해하는 데에 도움이 되었길 바랍니다!!