티스토리 뷰
다형성과 캐스팅
//부모 변수가 자식 인스턴스 참조(다형적 참조)
Parent poly = new Child();
//단, 자식의 기능은 호출할 수 없다. 컴파일 오류 발생
//poly.childMethod();
//다운캐스팅(부모 타입을 자식 타입으로)
Child child = (Child) poly;
child.childMethod();
//실행순서
Child child = (Child) poly; //다운캐스팅을 통해 부모타입을 자식 타입으로 변환한 뒤 대입
Child child = (Child) x001 //참조값을 읽을 다음 자식 타입으로 지정
//따라서 Parent poly의 타입이 변하는 것이 아닌 참조값이 Child 타입이 되는 것이다.
캐스팅 종류
((Child) poly).childMethod();
((Child) x001).childMethod(); //참조값을 읽은 다음 자식 타입으로 다운캐스팅
Child child = new Child();
Parent parent1 = (Parent) child; //업캐스팅은 생략 가능, 권장
Parent parent2 = child; //위와 동일
parent1.parentMethod();
parent2.parentMethod();
=> 이렇게 일시적 다운캐스팅을 사용하면 별도의 변수 없이 인스턴스의 자식 타입 기능을 사용할 수 있다.
=> 왜 다운캐스팅은 개발자가 직접 명시해야만할까..?
다운캐스팅과 주의점
Parent parent1 = new Child();
Child child1 = (Child) parent1;
child1.childMethod();
Parent parent2 = new Parent();
Child child2 = (Child) parent2; //런타임 오류: ClassCastException
child2.childMethod(); //실행 불가
=> 업캐스팅이 안전한 이유: 객체를 생성하면 해당 타입의 상위 부모 타입은 모두 함께 생성된다. 위로만 타입을 변경하면 업캐스팅은 메모리 상에 인스턴스가 모두 존재하기 때문에 안전하다. 따라서 캐스팅이 생략가능하다.
=> 다운캐스팅이 위험한 이유: 인스턴스에 존재하지 않는 하위 타입으로 캐스팅하는 문제가 발생한다. 객체 생성 시 부모 타입은 모두 생성되지만 자식 타입은 생성되지 않는다. 따라서 명시적으로 캐스팅해야만한다.
A,B,C는 상속 관계이다.
1) 업캐스팅 한 경우 하위타입인 C가 상위타입 B를 생성했을 때 객체를 생성할 때 하위 자식은 생성되지 않아 다운캐스팅은 인스턴스 내부에 없는 부분을 선택하는 문제가 발생한다.
C c = new B();
=> C c = (C) new B(); 와 같이 하위 타입으로 강제 다운캐스팅하더라도 메모리 상에는 B의 상위인 A밖에 없으므로 런타임 오류.
instanceof
parent instanceof Child
new Parent() instanceof Child
//parent 변수는 Parent 인스턴스를 참조하므로 false이다.
parent instanceof Child
new Child() instanceof Child
//parent 변수는 Child 인스턴스를 참조하므로 true이다.
public class CastMain5 {
public static void main(String[] args) {
Parent parent1 = new Parent();
call(parent1);
Parent parent2 = new Child();
call(parent2);
}
private static void call(Parent parent) {
parent.parentMethod();
if (parent instanceof Child) {
//=>Child c = new Parent();
System.out.println("Child 인스턴스이다!");
Child child = (Child) parent;
child.childMethod();
} else {
System.out.println("Child 인스턴스 아님");
}
}
}
메서드 오버라이딩
public class OverridingMain {
public static void main(String[] args) {
//자식 변수가 자식 인스턴스 참조
Child child = new Child();
System.out.println("Child -> Child");
System.out.println("value = " + child.value);
child.method();
//부모 변수가 부모 인스턴스 참조
Parent parent = new Parent();
System.out.println("Parent -> Parent");
System.out.println("value = " + parent.value);
parent.method();
//부모 변수가 자식 인스턴스를 참조하는 다형적 참조
Parent poly = new Child();
System.out.println("Parent -> Child");
System.out.println("value = " + poly.value); //변수는 오버라이딩x
poly.method(); //메서드는 오버라이딩O. 오버라이딩 된 메서드는 항상 우선권을 갖기 때문이다! Child.method
}
}
=> 상위 타입인 Parent의 메서드를 호출했을 때 하위 타입인 Child 메서드에 오버라이딩 되어 있으면 Child의 메서드를 호출하게 된다.
=> 기존 기능을 하위 타입에서 새로운 기능으로 재정의
=> 하나의 변수 타입으로 다양한 자식 인스턴스를 참조할 수 있게 된다.
'JAVA' 카테고리의 다른 글
[멀티스레드와 동시성] - 1. 프로세스와 스레드 (0) | 2024.07.25 |
---|---|
자바 채팅 프로그램 (0) | 2024.05.29 |
다형성2 (0) | 2024.01.15 |
1. JDK, JRE, JVM (0) | 2023.11.29 |
JAVA | null과 "" | 개념 (2) | 2023.08.03 |