Java

[인프런] 다형성

sejin2 2024. 5. 27. 17:04

객체지향 프로그래밍의 대표적인 특징으로는 캡슐화, 상속, 다형성이 있다. 
다형성은 이름 그대로 다양한 형태를 뜻한다. 프로그래밍에서 다형성은 한 객체가 여러 타입의 객체로 취급될 수 있는 능력을 뜻한다. 보통 하나의 객체는 타입으로 고정되어 있다. 그런데 다형성을 사용하면 하나의 객체가 다른 타입으로 사용될 수 있다는 뜻이다. 

다형적 참조

public class Parent {

    public void parentMethod() {
        System.out.println("Parent.parentMethod");
    }
}
public class Child extends Parent{
    public void childMethod() {
        System.out.println("Child.childMethod");
    }
}
public class PolyMain {
    public static void main(String[] args) {
        // 부모 변수가 부모 인스턴스 참조
        System.out.println("Parent -> Parent");
        Parent parent = new Parent();
        parent.parentMethod();
    }
}
  • 부모 타입의 변수가 부모 인스턴스를 참조한다.
  • new해서 Parent 인스턴스를 만들었다. 이 경우 부모 타입인 Parent를 생성했기 때문에 자식은 생성되지 않고 메모리 상에 Parent만 생성된다. 
  • 생성된 참조값을 Parent 타입의 변수인 parent에 담아둔다. 
  • parent.parentMethod( )를 호출하면 인스턴스의 Parent 클래스에 있는 parentMethod(  )가 호출된다.
 // 자식 변수가 자식 인스턴스 참조
        System.out.println("Child -> Child");
        Child child = new Child();
        child.parentMethod();
        child.childMethod();

  • 자식 타입의 변수가 자식 인스턴스를 참조한다.
  • new해서 Child 인스턴스를 만들었다. 이 경우 자식 타입인 Child를 생성했기 때문에 메모리 상에 Child와 Parent가 모두 생성된다. 
  • 생성된 참조값을 Child 변수 타입인 child에 담아둔다. 
  • child.childMethod(  )를 호출하면 인스턴스의 Child 클래스에 있는 childMethod( ) 가 호출 된다. 

다형적 참조 : 부모 타입의 변수가 자식 인스턴스 참조

// 부모 변수가 자식 인스턴스 참조 ( 다형적 참조 )
        System.out.println("Parent -> Child");
        Parent poly = new Child();
        poly.parentMethod();

  • 부모 타입의 변수가 자식 인스턴스를 참조한다. 
  • Child 인스턴스를 만들었는데, 이 경우 자식 타입인 Child를 생성했기 때문에 메모리 상에 Child와 Parent가 모두 생성된다. 
  • 생성된 참조 값은 Parent 타입의 변수인 poly에 담아둔다. 

부모는 자식을 담을 수 있다.

  • 부모 타입은 자식 타입을 담을 수 있다. 
  • Parent poly는 부모 타입으로 new Child( )를 통해 생성된 결과는 Child 타입이다. 자바에서 부모 타입은 자식 타입을 담을 수 있다. 
  • 반대로 자식 타입은 부모 타입을 담을 수 없다. 
// Child child1 = new Parent(); // 컴파일 오류 : 자식은 부모를 담을 수 없다.
// 자식의 기능을 호출할 수 없다. 컴파일 오류 발생
poly.childMethod();

다형적 참조
자바에서 부모 타입은 자신은 물론이고, 자신을 기준으로 모든 자식 타입을 참조할 수 있다. 손자가 있다면 손자의 타입도 참조할 수 있다. 이처럼 다양한 형태를 참조할 수 있다고 해서 다형적 참조라고 한다. 

다형적 참조와 인스턴스 실행

poly.parentMethod(  )를 호출하면 먼저 참조값을 사용해서 인스턴스를 찾는다. 그 다음으로 인스턴스 안에서 실행할 타입도 찾는다. poly는 Parent 타입이므로 Parent 클래스부터 시작해서 필요한 기능을 찾는다. 
인스턴스의 Parent 클래스에 parentMethod(  )가 있으므로 해당 메서드가 호출된다. 

poly에서 childMehtod( ) 호출이 안되는 이유 ?
childMehtod( )를 호출하면 참조값을 통해 인스턴스를 찾고 인스턴스 안에서 실행할 타입을 찾아야 한다. 
호출자인 poly는 Parent 타입이다. 따라서 Parent클래스 부터 시작해서 필요한 기능을 찾는다.
상속 관계는 부모 방향으로 찾아 올라갈 수는 있지만 자식 방향으로 찾아 내려갈 수는 없다. 
따라서 컴파일 오류가 발생하게 된다. 

이런 경우 childMehtod( ) 를 호출하고 싶다면 캐스팅이 필요하다 ! 

다형성과 캐스팅

public class CastingMain1 {
    public static void main(String[] args) {
        // 부모 변수가 자식 인스턴스 참조(다형적 참조)
        Parent poly = new Child();
        // 자식의 기능은 호출할 수 없다. 컴파일 오류 발생
        // poly.childMethod();
        
        // 다운캐스팅(부모 타입 -> 자식 타입)
        Child child = (Child) poly; // x001
        child.childMethod();
    }
}

poly는 Parent 타입으로 Parent는 최상위 부모이다. 상속 관계는 부모로만 찾아서 올라갈 수 있으므로 childMethod(  )는 자식 타입에 있으므로 호출 할 수 없기 때문에 컴파일 오류가 발생한다. 

다운캐스팅

부모는 자식을 담을 수 있지만 자식은 부모를 담을 수가 없다 ! 
이럴 때 다운캐스팅 기능을 사용해서 부모 타입을 잠깐 자식타입으로 변경해준다.
(타입) 처럼 괄호와 그 사이에 타입을 지정하면 참조 대상을 특정 타입으로 변경이 가능하다. 이렇게 특정 타입으로 변경하는 것을 캐스팅이라고 한다. 

실행 순서

Child child = (Child)poly // 다운캐스팅을 통해 부모타입을 자식 타입으로 변환한 다음에 대입 시도
Child child = (Child)x001 // 참조값을 읽은 다음에 자식 타입으로 지정
Child child = x001 // 최종 결과

캐스팅을 한다고 해서 Parent poly의 타입이 변하는 것이 아니라 해당 참조값을 꺼내고 꺼낸 참조값이  Child 타입이 되는 것이므로, poly의 타입은 그대로 Parent이다. 

  • 업캐스팅 : 부모 타입으로 변경
  • 다운캐스팅 : 자식 타입으로 변경

 

 

 

공부 내용: [인프런] 김영한의 실전 자바 - 기본편

'Java' 카테고리의 다른 글

[인프런] 다형성과 메서드 오버라이딩  (0) 2024.05.28
instanceof  (0) 2024.05.27
[인프런] super  (0) 2024.05.27
[인프런] 상속과 접근 제어  (0) 2024.05.27
[인프런] 상속과 메서드 오버라이딩  (0) 2024.05.27