상위 클래스로 형 변환된 인스턴스는 상위 클래스에 없는 멤버변수와 메소드는 사용할 수 없다. 다만 같은 메소드가 재정의 된 경우 가상 메소드에 의해 자신의 메소드를 사용할 뿐이었다. 그런데 필요에 의해 다시 하위 자료형으로 형 변환되어 멤버변수나 메소드를 사용해야 할 경우가 있을 수 있다. 다시 하위 자료형으로 형 변환하는 것을 다운 캐스팅(down casting)이라고 한다.

 

1. 다운 캐스팅


상위 클래스를 상속받는 하위 클래스가 여러개인 경우 다시 하위 클래스로 돌아오기 전에 하위 클래스들 중 어떤 클래스의 객체인지 확인해야 한다. 예를 들어 고객이라는 상위 클래스를 상속받은 VIP고객, Gold고객, Silver고객이 있다고 하자. 고객 자료형으로 선언된 VIP고객의 인스턴스가 다시 하위 자료형으로 갈 때 Gold 고객이나 Silver고객 자료형으로 다운캐스팅이 되어서는 안된다. 따라서 어떤 클래스의 인스턴스인지 확인해야 하는데 이를 해주는 것이 instanceof 예약어이다.

package inheritance;

public class Animal {
   public void move() {
      System.out.println("animal moves");
   }
}
package inheritance;

public class Human extends Animal{
   public void move() {
      System.out.println("human walks");
   }

   public void readBook() {
      System.out.println("human reads a book");
   }
}
package inheritance;

public class Tiger extends Animal{
   public void move() {
      System.out.println("tiger runs");
   }

   public void hunting() {
      System.out.println("tiger hunts");
   }
}
package inheritance;

public class Eagle extends Animal {
   public void move() {
      System.out.println("eagle flys");
   }

   public void spreadWings() {
      System.out.println("eagle spreads wings");
   }
}

Animal 상위 클래스를 상속받는 Human, Tiger, Eagle 클래스가 있다. 각 클래스는 Animal의 move() 메소드를 재정의하고 추가적으로 자신만의 메소드를 하나 더 만들었다.

package inheritance;
import java.util.ArrayList;

public class AnimalTest {

   ArrayList<Animal> aniList = new ArrayList<Animal>();

   public static void main(String[] args) {
      AnimalTest aTest = new AnimalTest();
      aTest.addAnimal();
      aTest.testCasting();
   }

   public void addAnimal() {
      aniList.add(new Human());
      aniList.add(new Tiger());
      aniList.add(new Eagle());

      for(Animal ani : aniList) {
         ani.move();
      }
   }

   public void testCasting() {
      for(int i=0; i<aniList.size(); i++) {
         Animal ani = aniList.get(i);
         if(ani instanceof Human) {
            Human h = (Human)ani;
            h.readBook();
         }
         else if(ani instanceof Tiger) {
            Tiger t = (Tiger)ani;
            t.hunting();
         }
         else if(ani instanceof Eagle) {
            Eagle e = (Eagle)ani;
            e.spreadWings();
         }
         else {
            System.out.println("No such a type!");
         }
      }
   }
}

AnimalTest라는 클래스를 하나 만들고 Animal자료형을 요소로 가지는 ArrayList를 하나 만들었다. 그리고 세 가지 하위클래스 각각의 객체를 생성하는 add()메소드와 참조변수가 참조하는 객체의 참조자료형을 확인한 후 맞는 자료형으로 변경한 후 각 하위 클래스만이 가지는 고유의 메소드를 호출한다. 이 때 if else 문을 사용했다.

실행결과

human walks

tiger runs

eagle flys

human reads a book

tiger hunts

eagle spreads wings

instanceof 예약어를 사용하여 참조변수가 어떤 하위 클래스의 객체를 참조하는지 매칭하여 다운캐스팅을 하였다. 다운캐스팅 된 객체를 새로운 참조변수에 저장하고 이 참조변수를 통해서 각 객체의 고유 메소드를 호출할 수 있었다.

'프로그래밍 언어 > Java' 카테고리의 다른 글

(Java) 34 - final 선언  (0) 2020.05.17
(Java) 33 - 추상 클래스  (0) 2020.05.17
(Java) 31 - 다형성  (0) 2020.05.17
(Java) 30 - 메소드 오버라이딩  (0) 2020.05.17
(Java) 29 - 상속  (0) 2020.05.17

+ Recent posts