JAVA 입문 - 다운 캐스팅과 instanceof
지난 글: [프로그래밍 언어/JAVA] - JAVA 입문 - 다형성 활용
하위 클래스로 형 변환, 다운 캐스팅
상속에서 클래스 생성과 형 변환글에서 상위 클래스로 형 변환이 묵시적으로 이루어지는 과정을 배웠었다. 이제 다시 하위 클래스로 형 변환이 되는 과정을 살펴보자.
지난 번에 구현한 Animal 클래스와 Human 클래스를 생각해보자. Human 클래스는 Animal 클래스를 상속 받았기 때문에 Animal ani = new Human( ); 코드를 사용할 수 있다. 이때 생성된 인스턴으 Human은 Animal형이다. 이렇게 Animal형으로 형 변환이 이루어진 경우에 Animal 클래스에서 선언한 메서드와 멤버 변수만 사용할 수 있다. Human 클래스에 더 많은 메서드가 구현되어 있고 다양한 멤버 변수가 있다 해도 자료형이 Animal형인 상태에서는 사용할 수가 없다. 따라서 필요에 따라 다시 원래 인스턴스의 자료형으로 되돌아가야 하는 경우가 있다. 이렇게 상위 클래스로 형 변환되었던 하위 클래스를 다시 원래 자료형으로 형 변환하는 것을 다운 캐스팅(down casting)이라고 한다.
instanceof
상속 관계를 생각해보자. 모든 인간은 동물이지만 모든 동물이 인간은 아니다. 따라서 다운 캐스팅을 하기 전에 상위 클래스로 형 변환된 인스턴스의 원래 자료형을 확인해야 변환할 때 오류를 막을 수 있다. 이를 확인하는 예약어가 instance of이다. instanceof는 아래와 같이 사용할 수 있다.
Animal hAnimal = new Human( );
if(hAnimal instanceof Human) { //hAnimal 인스턴스 자료형이 Human형이라면
Human human = (human)hAnimal; //인스턴스 hAnimal을 Human형으로 다운 캐스팅
위 코드에서 사용한 참조 변수 hAnimal은 Human형으로 생성되었지만 Animal형으로 형 변환되었다. instanceof 예약어는 왼쪽에 있는 변수의 원래 인스턴스형이 오른쪽 클래스 자료형인가를 확인한다. 코드를 보면 hAnimal은 Animal형으로 되어있지만 원래는 Human형으로 생성된 인스턴스인지 확인하는 것이다. instanceof의 반환 값이 true면 다운 캐스팅을 하는데, 이때는 Human human = (Human)hAnimal; 문장처럼 명시적으로 자료형을 써 주어야 한다. 상위 클래스로는 묵시적 형 변환이 되지만 하위 클래스로 형 변환을 할 때는 명시적으로 해야한다. 또 instanceof로 인스턴스형을 확인하지 않으면 오류가 발생할 수도 있다.
아래처럼 원래 자료형이 Human이 아닌 경우
Animal ani = new Tiger( );
Human h = (Human)ani;
이처럼 코딩해도 컴파일 오류는 나지 않는다. 이유는 Tiger 인스턴스가 Animal형으로 자동 형 변환이 되고, 변수 h의 자료형 Human과 강제 형 변환되는 ani의 (Human)형이 동일하기 때문이다. 하지만 이 코드를 실행하면 오류가 발생한다. 따라서 참조 변수의 원래 인스턴스형을 정확히 확인하고 다운 캐스팅을 해야 안전하다. 그러면 원래 인스턴스형으로 다운 캐스팅하는 예를 보자.
시나리오:
Animal 클래스를 상속받은 여러 동물 클래스가 있다. Human, Tiger, Eagle 클래스에는 각각 다른 메서드도 추가로 구현했다.



각 동물 클래스를 인스턴스로 생성하여 Animal형으로 선언한 배열에 추가한다. 이때 호출할 수 있는 메서드는 Animal 클래스에 선언된 메서드뿐이다. 20~22행에서 향상된 for문을 사용해 모든 배열 요소를 하나씩 꺼내 move( ) 메서드를 호출하면 재정의된 메서드가 호출된다. 하지만 배열 요소가 Animal형이므로 각각의 하위 클래스에 선언된 readBook( ), hunting( ), flying( ) 메서드를 사용할 수 없다. 앞의 세 메서드를 호출하기 위해서는 다시 원래 자료형으로 다운 캐스팅되어야 한다. instanceof를 활용하여 실제 인스턴스형을 확인한 후에 다운 캐스팅을 하여 각 클래스에 있는 메서드를 호출했다.
참고 서적: 자바 프로그래밍 입문 - 박은종