inflearn

[인프런] 김영한의 자바 기본 강의 섹션10. 다형성1 (240113)

hail2y 2024. 1. 14. 00:34

1/13 섹션10 다형성1 필기

객체지향 프로그램의 대표적인 특징은 캡슐화, 상속, 다형성이라고 한다. 그 중에서 다형성은 객체 프로그래밍의 꽃이라고 한다. 중요한 만큼 집중해서 봐야지! 

  • 다형성: 다양한 형태, 여러 형태로!
    한 객체가 여러 타입의 객체로 취급될 수 있는 능력
    - 다형적 참조, 메서드 오버라이딩

다형적 참조

다양하게 참조할 수 있다.

 

부모 타입은 자식 타입을 담을 수 있다. ex) Parent parent = new Child(); - 가능

-- 부모 타입의 변수가 자식 인스턴스를 참조한다. 하지만 자식 인스턴스의 메서드는 호출이 불가하다.

 

반대로 자식 타입은 부모 타입을 담을 수 없다. ex) Child child = new Parent(); - 불가, 컴파일 오류 발생

  • 다형적 참조: 본인 포함 본인 하위의 타입들까지 담을 수 있다.  
  • 상속 관계에 놓은 타입들만 담을 수 있고, 아무 관계 없는 것은 담을 수 없다. 
  • 상속 관계는 부모 방향으로 찾아 올라갈 수는 있지만 자식 방향으로 찾아 내려갈 수는 없다.

인스턴스에 자식 메서드가 있는데 호출을 하려면 캐스팅이 필요하다

부모 타입을 사용하는 변수를 자식 타입에 대입하려고 하면 컴파일 오류가 발생한다.

다운캐스팅

  • 다운캐스팅: 부모 타입을 자식 타입으로 변경한다, 담는다 
// 부모 변수가 자식 인스턴스 참조 (다형적 참조)
Parent poly = new Child();

// 다운캐스팅(부모 타입 -> 자식 타입)
Child child = (Child) poly;
child.childMethod(); // 가능

 

일시적 다운캐스팅

. 과 () 중 연산자 우선순위가 높은 것은 . 이기 때문에 캐스팅을 먼저 해주기 위해서 괄호로 묶어준다.

((Child) poly).childMethod();

  • 업캐스팅은 생략이 가능하다. (권장) -- 안전; 상위 부모 타입이 모두 존재하기 때문
  • 다운캐스팅을 잘못 하면 심각한 런타임오류가 발생할 수 있다.
  • 자바에서는 사용할 수 없는 타입으로 다운캐스팅 하는 경우에 ClassCastException 예외를 발생시킨다. 예외 발생 시 다음 동작이 실행되지 않고 프로그램이 종료된다. 
  • 다운캐스팅의 경우 인스턴스에 존재하지 않는 하위 타입으로 캐스팅하는 문제 발생할 수 있다. -- 위험

컴파일 오류는 컴파일 전 문법적 오류를 알려주기 때문에 좋은 오류이지만 런타임 오류는 좋지 못한 오류다. 런타임오류는 프로그램이 실행되고 있는 시점에 발생한다. 보통 고객이 해당 프로그램을 실행하는 도중에 발생한다. 

instanceof 키워드

변수가 참조하는 인스턴스의 타입을 확인하고자 할 때 사용한다.

private static void call(Parent parent) {
	parent.parentMethod();
    if (parent instanceof Child) {
    	System.out.println("Child 인스턴스 맞음");
    	Child child = (Child) parent;
        child.childMethod();
    }
}

 

parent instanceof Child

Child c = new parent(); -- false

Child c = new Child(); -- true

 

오른쪽에 있는 타입에 왼쪽에 있는 인스턴스의 타입이 들어갈 수 있는지 대입해 본다. 크로스해서 인스턴스 생성해 본다!

 

cf. 자바 16 - 아직은 많이 사용하는 개념이 아니지만 사용하게 될 개념

if (parent instanceof Child child)

instanceof를 사용하면서 동시에 변수를 선언할 수 있다. 조건이 만족되면 직접 캐스팅을 하지 않을 수 있다.

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

오버라이딩 된 메서드가 항상 우선권을 가진다!

멤버 변수는 오버라이딩 되지 않는다. 

 

메서드 오버라이딩의 힘은 다형성과 함께 사용할 때 나타난다.

Parent poly = new Child(); // 다형적 참조
System.out.println("value = " + poly.value); // parent의 value
poly.method(); // child의 method

 

Parent와 Child에 필드명 (value)도 같고, 메서드명(method())도 같다고 할 때 필드는 parent가 출력되지만, 메서드는 오버라이딩이 된 child의 메서드가 호출된다. 

=> 오버라이딩 된 메서드는 항상 우선권을 가진다! 더 하위 자식의 오버라이딩 된 메서드가 우선권을 가지는 것이다. 

 

메서드를 호출하면,

1. 이 메서드가 오버라이딩이 됐는지를 확인한다. 

2. 오버라이딩이 됐으면 자식 메서드의 것이 실행된다.

 

정리하면,

다형성 - 다형적 참조, 메서드 오버라이딩
1. 다형적 참조 : 하나의 변수 타입으로 다양한 자식 인스턴스를 참조할 수 있는 기능
2. 메서드 오버라이딩:  기존 기능을 하위 타입에서 새로운 기능으로 재정의

 

--끝--