티스토리 뷰

JAVA

다형성1

Howu 2024. 1. 7. 10:37

다형성과 캐스팅

//부모 변수가 자식 인스턴스 참조(다형적 참조)
        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
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함