자바 - Child obj = new Child()와 Parent obj = new Child() 차이 (feat. 업캐스팅)
업캐스팅 예시
import java.util.ArrayList;
import java.util.List;
public class UpCastingExample {
public static void main(String[] args) {
ArrayList<String> listOne = new ArrayList<String>(); // 일반적인 객체 생성
List<String> listTwo = new ArrayList<String>(); // 업캐스팅을 한 객체 생성
System.out.println(listOne.getClass()); // class java.util.ArrayList
System.out.println(listTwo.getClass()); // class java.util.ArrayList
}
}
자바에서 동적 배열을 사용하기 위해 위와 같이 두 개의 리스트를 생성했다.
getClass() 메소드를 활용해 두 인스턴스의 클래스 정보를 확인했더니 둘 다 ArrayList 클래스의 객체이다.
listOne 인스턴스는 ArrayList 타입이고 listTwo는 List 타입으로 정의했는데, 타입만 다른 두 개의 객체는 무슨 실제로는 무슨 차이가 있을까?
업캐스팅을 한 객체의 다른점
public class UpCastingExample {
public static void main(String[] args) {
// childWithUpCasting라는 인스턴스는 Child 클래스의 객체이며 타입은 Parent이다
Parent childWithUpCasting = new Child();
// child라는 인스턴스는 Child 클래스의 객체이며 타입도 Child이다
Child child = new Child();
childWithUpCasting.parentMethod(); // 부모 메소드
// childWithUpCasting.childMethod(); 에러: childMethod 메소드 미존재
child.parentMethod(); // 부모 메소드
child.childMethod(); // 자식 메소드
}
}
class Parent {
public void parentMethod() {
System.out.println("부모 메소드");
}
}
class Child extends Parent {
public void childMethod() {
System.out.println("자식 메소드");
}
}
child 인스턴스는 예상대로 Parent 클래스로부터 상속받은 parentMethod() 메소드와 Child 클래스에 속한 childMethod() 메소드 실행이 가능하다.
다만 childWithUpCasting 인스턴스는 선언 시, 타입이 Parent 클래스로 업캐스팅이 됨 (Parent 클래스를 참조함).
결과: childWithUpCasting 인스턴스는 Parent 클래스를 참조하기 때문에 Parent 클래스의 메소드와 멤버 변수만 사용이 가능하므로 parentMethod() 메소드만 실행 가능.
실험: 자식 클래스가 부모 클래스의 A라는 메소드를 오버라이드 한 경우, 업캐스팅 된 객체가 메소드 A 실행 시, 부모의 메소드를 실행? 자식이 이미 오버라이드 한 메소드를 실행?
public class UpCastingExample {
public static void main(String[] args) {
Parent childWithUpCasting = new Child();
Child child = new Child();
childWithUpCasting.parentMethod(); // 자식으로부터 오버라이드 된 부모 메소드
// childWithUpCasting.childMethod(); 실행 불가 (childMethod 메소드 미존재)
child.parentMethod(); // 자식으로부터 오버라이드 된 부모 메소드
child.childMethod(); // 자식 메소드
}
}
class Parent {
public void parentMethod() {
System.out.println("부모 메소드");
}
}
class Child extends Parent {
@Override
public void parentMethod() {
System.out.println("자식으로부터 오버라이드 된 부모 메소드");
}
public void childMethod() {
System.out.println("자식 메소드");
}
}
childWithUpCasting 인스턴스의 타입은 Parent 이어서 Parent 클래스에 정의된 parentMethod() 메소드를 호출할 줄 알았지만
오버라이드도 재정의된 Child 클래스의 parentMethod() 메소드를 호출했다.
정리
Parent obj = new Child();
업캐스팅된 obj 객체의 속성
ㄴ 클래스: Child
ㄴ 타입: Parent
ㄴ 특징: Parent 클래스에 정의된 메소드와 멤버 변수만 접근 가능. 단, 메소드 호출 시, Child 클래스에서 이미 오버라이드 된 경우, 오버라이드한 메소드를 호출.