[Java] 다형성

정석·2024년 2월 1일

Java

목록 보기
31/39
post-thumbnail

김영한의 자바 강의 내용을 듣고 정리한 내용입니다.

다형성이란?

'다양한 형태' 를 의미한다. 즉, 하나의 객체가 다른 타입으로 사용할 수 있는 기능을 말한다.

먼저 이해하고 가야 할 부분으로, 부모 타입의 인스턴스가 메서드를 호출할 때 타입이 부모이기 때문에 부모 메서드를 참조하게 된다. 또한 부모를 상속하고 있는 자식 메서드는 생성되지 않는다. 아래 그림을 보며 이해하자.

  • Parent parent = new Parent()

부모 인스턴스가 생성된 곳에 부모의 메서드만 존재하는 것을 볼 수 있다. 상속된 자식 인스턴스는 생성되지 않는다.


하지만, 자식 타입으로 자식 인스턴스를 생성하면 아래와 같은 모습이 된다.

  • Child child = new Child()

위 그림에서 볼 수 있듯이 자식 타입의 인스턴스를 생성하면 부모의 메서드도 생성됨을 알 수 있다. 그리고 메서드는 인스턴스의 타입인 child 타입에 대한 메서드를 먼저 가리키게 된다. 해당 타입의 메서드가 존재하지 않을 때 부모 타입의 메서드를 호출한다.


그런데 만약 부모 타입으로 자식 인스턴스를 참조하게 되면 어떻게 될까?

자식 인스턴스를 참조했기 때문에 자식 메서드도 메모리상 생기게 된다. 하지만 타입은 부모 타입이므로 메서드 호출 시 부모 메서드를 먼저 참조한다. 그림으로 보면 아래와 같다.

  • Parent temp = new Child()

위와 같이 부모타입으로 자식을 참조할 수 있지만, 반대로 자식 타입으로 부모를 참조하는 건 안된다.

Child temp2 = new Parent() // 사용 불가, 오직 부모만 자식을 담을 수 있다.

다형적 참조의 한계

바로 위의 그림처럼 부모 타입으로 자식을 참조하여 인스턴스를 생성했을 때, 만약 자식메서드를 사용하고 싶다면 바로 사용할 수 없다. 부모타입으로 자식타입의 메서드를 호출 할 수 없기 때문이다. 이때 사용하는 것이 다운캐스팅 이다.

'cast' 의 어원은 금속 혹은 다른 물질을 녹여 다른 형태로 만드는 것

Parent temp = new Child(); // 부모 타입으로 자식 인스턴스 생성
temp.childMethod() // 컴파일 오류 -> temp는 부모 타입을 갖고 있기 때문

Child child = (Child) temp; // temp 를 Child 타입으로 다운캐스팅하고 해당 참조값을 Child 타입 변수에 저장
child.childMethod();

이 코드를 그림으로 보자면 아래와 같다.

- 일시적 다운캐스팅

((Child) temp).childMethod();

instaceof

  • 다형성에서 참조형 변수는 여러 대상을 참조할 수 있기에 어떤 대상을 참조하고 있는지 확인할 때 사용한다.
public static void main(String[] args) { 

	Parent parent1 = new Parent(); 
    System.out.println("parent1 호출"); 
    call(parent1);
    
    Parent parent2 = new Child(); 
    System.out.println("parent2 호출"); 
    call(parent2);
}

private static void call(Parent parent) {
	parent.parentMethod();
    if (parent instanceof Child) {
		System.out.println("Child 인스턴스"); 
        Child child = (Child) parent; 
        child.childMethod();
  • 결과
parent1 호출
Parent.parentMethod
parent2 호출
Parent.parentMethod
Child 인스턴스
Child.childMethod

다형성과 메서드 오버라이딩

오버라이딩 된 메서드가 항상 우선권을 가진다!!! (실행의 우선권)

자식 클래스에서 부모의 메서드를 오버라이딩 했다면, 부모 타입의 인스턴스에서 부모 메서드를 호출 했을 때 오버라이딩 된 메서드 있기 때문에 자식 메서드가 실행된다. (해당 경우는 부모타입으로 자식 인스턴스를 참조 했을 때만 가능 -> 그래야 자식 메서드가 메모리상에 생기기 때문)

  • 부모 클래스
public class Parent {
	
    public Stirng value = "parent";
    
    public void method() {
    	System.out.println("Parent.method");
    }
}       
  • 자식 클래스
public class Child extends Parent {
	
    public Stirng value = "child";
    
    @Override
    public void method() {
    	System.out.println("Child.method");
    }
}       
  • 메인
public class Main() {
	public static void main(String[] args) {
    
    	// 자식 타입으로 자식 인스턴스 참조
        Child child = new Child();
        child.method();
        
        // 부모 타입으로 부모 인스턴스 참조
        Parent parent = new Parent();
        parent.method();
        
        // 부모 타입으로 자식 인스턴스 참조 (다형적 참조)
        Parent temp = new Child();
        temp.method(); // 메서드 오버라이딩 확인되면, 오버라이딩 된 메서드가 우선권을 가짐

0개의 댓글