업캐스팅(upcasting): 서브 클래스 객체에 대한 레퍼런스를 슈퍼 클래스 타입으로 변환
- 자바에서 서브 클래스 객체는 슈퍼 클래스의 멤버를 모두 가짐
- 서브 클래스의 객체를 슈퍼 클래스의 객체로 취급 가능
- 업캐스팅은 슈퍼 클래스의 레퍼런스로 서브 클래스의 객체를 가리키게 함
class Person{...}
class Student extends Person{...}
public class Main{
public static void main(String[] args){
Person p;
Student s = new Student();
p = s; //업캐스팅
}
}
슈퍼 클래스인 Person 타입의 p가 서브 클래스인 Student의 객체를 가리키게 되지만, p를 Person 타입으로 선언했으므로 p는 Person 클래스의 멤버에만 접근 가능
다운캐스팅(downcasting): 슈퍼 클래스 객체의 레퍼런스를 서브 클래스 타입으로 변환
- 업캐스팅과 반대
- 업캐스팅되었던 객체의 자료형을 되돌림
- 개발자의 명시적 타입 변환 필요
class Person{...}
class Student extends Person{...}
public class Main{
public static void main(String[] args}{
Person p = new Student("홍길동"); //업캐스팅
Student s;
s = (Student)p; //다운캐스팅, (Student)의 명시적 타입 변환
}
}
Person p=new Student("홍길동"); 코드를 통해 Student 객체를 Person 타입의 레퍼런스 p로 가리키므로 업캐스팅
s=(Student)p; 코드로 Person 타입의 p를 Student 타입의 레퍼런스 s로 변환하였으므로 다운캐스팅
s를 통해 Student 객체 전체에 접근 가능
이 개념이 너무 어려웠다
시험 당일 아침까지도 이해를 못 해서 그냥 업캐스팅은 슈퍼 클래스가 먼저, 다운캐스팅은 서브 클래스가 먼저 이런 식으로 형식만 외우고 들어갔던 기억이 난다;
SuperClass s1 = new SubClass(); //서브 클래스를 슈퍼 클래스로 형변환
SubClass s2 = (SubClass)s1; //슈퍼 클래스를 서브 클래스로 형변환
우변의 데이터 타입을 좌변의 데이터 타입으로 변환한다고 생각하면 된다
Student s = new Student();
Person p = s; //업캐스팅
s가 Student 타입으로 선언되고 Student 타입의 메모리가 할당된 서브 클래스 객체이며, 레퍼런스 p는 Person 타입으로 선언된 상황에서
Person p = s;
문을 통해 레퍼런스 p가 객체 s를 가리키도록 치환되었다
업캐스팅을 통해 Person 타입의 p는 서브 클래스 객체를 가리키도록 치환되었고
p는 Person 타입으로 선언되었으므로 Person 클래스의 멤버에만 접근할 수 있다 (위 경우에는 grade, department에 접근할 수 없다)
Person p = new Student("홍길동"); //업캐스팅
Student s = (Student)p; //다운캐스팅
위 코드에서 레퍼런스 p는 Person타입으로 선언, Student 타입으로 할당받아 업캐스팅되었다
이때 서브 클래스의 정보를 모두 담을 수 있는 객체 p의 타입이 슈퍼 클래스로 선언된 것을 서브 클래스 Student 타입으로 되돌리는 것이 다운캐스팅이다
업캐스팅과 instanceof 연산자
- 슈퍼 클래스는 여러 서브 클래스에 상속
- 업캐스팅된 레퍼런스로 객체의 타입 판단 어려움
- instanceof 연산자를 사용하여 레퍼런스가 가리키는 객체의 타입을 식별
class Person{
...
}
class Student extends Person{
...
}
class Researcher extends Person{
...
}
class Professor extends Researcher{
...
}
public class Main{
public static void main(String[] args){
Person p = new Person();
Person p = new Student(); //업캐스팅
Person p = new Researcher(); //업캐스팅
Person p = new Professor(); //업캐스팅
}
}
- 레퍼런스 p가 Person, Student, Researcher, Professor 중 어떤 객체를 가리키는지 알 수 없음
- 이 경우 타입 식별을 위해 instanceof 연산자를 사용
instanceof 연산자 사용
레퍼런스 instanceof 클래스명
- instanceof 연산자의 결과 값은 boolean 타입
- 레퍼런스가 가리키는 객체가 해당 클래스 타입의 객체이면 true, 아니면 false
- instanceof는 클래스에만 적용
Person jee = new Student();
Person kim = new Professor();
Person lee = new Researcher();
if(jee instanceof Person) //true
if(jee instanceof Student) //true
if(kim instanceof Student) //false
if(kim instanceof Professor) //true
if(kim instanceof Researcher) //true
if(lee instanceof Professor) //false
if(3 instanceof int) //오류, instanceof는 객체에 대한 레퍼런스만 사용
if("java" instanceof String) //오류 아님, String은 객체
예제 5-4 아래 코드의 실행 결과
class Person{}
class Student extends Person{}
class Researcher extends Person{}
class Professor extends Researcher{}
public class InstanceOfEx {
static void print(Person p) {
if(p instanceof Person) System.out.print("Person ");
if(p instanceof Student) System.out.print("Student ");
if(p instanceof Researcher) System.out.print("Researcher ");
if(p instanceof Professor) System.out.print("Professor ");
System.out.println();
}
public static void main(String[] args) {
System.out.print("new Student() ->\t");
print(new Student());
System.out.print("new Researcher() ->\t");
print(new Researcher());
System.out.print("new Professor() ->\t");
print(new Professor());
}
}