다형성과 메서드에 관하여
public abstract class Animal {
protected abstract void move();
}
public class Bird extends Animal {
@Override
public void move() {
System.out.println("날라다닌다");
}
}
public class Human extends Animal {
@Override
public void move() {
System.out.println("두발로 직립 보행");
}
public void reading() {
System.out.println("독서를 한다.");
}
}
public class Tiger extends Animal {
@Override
public void move() {
System.out.println("네발로 뛰어다닌다.");
}
public void hunting() {
System.out.println("사냥을 한다.");
}
}
위와같은 상속 클래스가 있을때, 다형성을 이용하여 자료형을 맞춰 한 배열에 정의하는 것이 가능하다.
public class Ex01 {
public static void main(String[] args) {
Animal human = new Human(); // Animal
//human.move();
Animal tiger = new Tiger();
//tiger.move();
Animal bird = new Bird();
//bird.move();
Animal[] animals = new Animal[3];
animals[0] = human;
animals[1] = tiger;
animals[2] = bird;
for (Animal animal : animals) {
animal.move();
}
}
}
여기서 의문점이 생겼다.
더 좁은 범위를 가진 부모클래스(Animal)를 상속 받았을 때, 분명
animal[]은 new Human객체로 생성하였지만 Animal 자료형으로 범위를 제한뒀다.
그런데 윗 출력값을 봤을떄, 오버로드 되어서
두발로 직립 보행
네발로 뛰어다닌다.
날라다닌다.
와 같은 값이 출력된다.
여기서 의문인 것은 Human 객체이지만, Anumal 자료형으로 제한했기떄문에 Human 객체의 메서드를 사용할 수 없어야하지만 정작 출력값은 Human에서 정의한 메서드 출력값이였다.
해결
하위 클래스의 자원은 사용못하는 것이 맞다. 그러나 객체가 생성될 때 오버로드된 메서드 같은 경우에는 메서드 테이블에 주소가 저장된다. 이때, 하위 객체의 주소값이 맵핑된 이후에 자원들에 제한이 걸리게 된다.
즉, 핵심은 객체가 생성될 때의 생성자 클래스를 기준으로 메서드 테이블이 작성된다. 위 예시로 설명하자면 Human 객체의 move메서드 주소가 메서드 테이블에 작성되는 것이다.
그렇기에 모든 다형성 구조를 가진 클래스들에서 메서드를 사용할때, 상위 메서드로 사용이 가능한 것이다.