7-2 다형성

Cloudman·2022년 12월 7일
0

항해99 자바 공부

목록 보기
9/10

★ 진행과정 ★

  • 클래스 (6 챕터)
    ◎ 스터디 그룹으로 진행
    ▷ 7-1 : 상속
    ▶ 7-2 : 타입 변환과 다형성
    ▷ 7-3 : 추상 클래스



📒 다형성

하나의 객체가 여러 가지 타입을 가질 수 있는 것
다형성의 사용 방법 자체는 동일하지만 다양한 객체를 이용해서 다양한 실행결과가 나오도록 하는것을 말한다.

  • 객체지향의 주요 특징 중 하나
  • 상속을 통해 기능을 확장 및 변경이 가능
  • 같은 클래스 내에 코드 길이를 줄이기가 가능하다.

다형성의 구현을 위해서는 메소드 재정의와 타입 변환이 필요하다.



📋 자동 타입 변환

묵시적 타입 변환 이라고도 한다.
대입 연산이난 산술 연산에서 컴파일러가 자동으로 수행해주는 타입 변환을 말한다.
즉, 프로그램 실행 도중에 자동으로 일어나는 타입 변환을 말한다.

자동 타입 변환은 아래와 같은 조건에서 발생한다.


간단한 예제를 들면...

double num1 = 10;			// 결과 : 10.0
int num2 = 3.14;			// 컴파일 에러 발생
double num3 = 7.0f + 3.14;	// 결과 : 10.14
  • 첫번째는 double 타입 변수에 int 타입 데이터를 넣었으므로, double 타입으로 자동 타입 변환이 되었다.
  • 두번째는 int 타입 변수가 표현할 수 있는 범위보다 더 큰 double 타입 데이터를 대입해서 컴파일 에러가 발생
  • float 타입과 double 데이터의 연산에서는 더 큰 double 타입으로 자동 타입 변환 되었다.



🔖 클래스에서의 타입 변환

위 사진을 보면 클래스의 변환은 상속 관계에 있는 클래스 사이에서 발생하는 것을 잘 나타낸다.

위 그림을 아래의 코드처럼 만들어 보면서 실습


위 같은 상황이 일반적인데 단, 예외또한 존재한다.

메소드가 자식 클래스에서 재정의 되었다면, 자식 클래스의 메소드가 대신 호출된다.

이는 다형성과 관련이 있기 때문에 매우 중요한 성질이므로 잘 알아두어야 한다.

위 사진을 보면 Child 객체는 method3() 메소드를 가지고 있지만,
Parent 타입으로 변환된 이후에는 method3() 를 호출할 수 없다.
다만, method2() 메소드는 부모 자식 모두에게 있기 때문에 이렇게 재정의된 메소드는 타입 변환 이후에도 자식 메소드가 호출된다.

위의 예시를 좀 더 알아보기 쉽게 프린트문으로 출력까지 해보면 아래와 같다.




📋 필드의 다형성

자식 타입으로 사용하지 않고 부모 타입으로 변환해서 사용하는 이유는 다형성을 구현하기 위해서다.
필드의 타입을 부모 타입으로 선언시, 다양한 자식 객체의 저장이 가능하여 필드의 사용 결과가 달라질 수 있다.
이를 필드의 다형성 이라고 한다.

구현방식의 예

  • 상속 : 부모클래스를 상속하는 자식 클래스는 부모가 가지고 있는 필드와 메소드를 가지고 있으므로 사용 방법이 동일하다.
  • 오버라이딩 : 자식 클래스는 부모의 메소드를 오버라이딩(재정의) 해서 메소드의 실행 내용을 변경함으로써 더 우수한 실행 결과가 나올 수 있게 한다.
  • 타입 변환 : 교체 가능성 즉, 자식 타입을 부모 타입으로 변환이 가능하다.(다형성)

예제 코드 및 실행 결과...




📋 매개 변수의 다형성

참조형 매개변수는 메서드 호출시, 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있다.
매개값을 다양화하기 위해 매개 변수에 자식 객체의 지정이 가능하다.

class Driver {
	void drive(Vehicle vehicle) {
		vehicle.run();
    }
}

위처럼 Drive 클래스에 drive() 메소드가 정의되어 있고 Vehicle 타입의 매개변수가 선언되어 있다.

drive() 메소드를 정상적으로 호출시 다음과 같을 것이다.

Driver driver = new Driver();
Vehicle vehicle = new Vehicle();
driver.drive(vehicle);

만약 Vehicle 의 자식 클래스인 Bus 객체를 drive() 메소드의 매개값으로 넘겨준다면??

drive() 메소드 Vehicle 타입을 매개 변수로 선언했지만, Vehicle 을 상속받는 Bus 객체가 매개값으로 사용되면 자동 타입 변환이 발생한다.

Vehicle vehicle = bus;
		  ↑________↑
         자동 타입 변환

위의 관계들을 코드를 직접 짜면서 아래와 같이 만들면서 해 보았다.




📋 강제 타입 변환

부모 타입을 자식 타입으로 변환하는 것을 말합니다.
모든 부모 타입을 자식 타입으로 강제변환이 가능한 것은 아니다.
자식 타입이 부모 타입으로 자동 타입 변환 후 다시 자식 타입으로 변환할 때 강제 타입 변환을 사용할 수 있다.

자식타입 변수 = (자식타입) 부모타입;
	↑_____________________↑
   부모 타입을 자식 타입으로 변환

Parent parent = new Child(); : 자동 타입 변환
Child child = (Child) parent; : 강제 타입 변환

위처럼 Child 객체가 Parent 타입으로 자동 변환된 상태에서
다시 원래 Child 로 강제 변환이 가능하다.


위 이미지를 보면 field2 필드와 method3() 메소드는 Child 타입에만 선언되어 있으므로 Parent 타입으로 자동 타입 변환시엔 사용이 불가능하다.
하지만 다시 Child 타입으로 강제 변환하면 사용이 가능하다.




📋 객체 타입 확인

이런식으로 타입이 바뀌는 경우 부모 변수가 참조하는 객체가 부모 객체인지, 자식 객체인지 확인하는 방법이 있다.
이럴때 사용 하는 연산자가 instanceof 연산자 이다.

boolean result = 좌항(객체) instanceof 우항(타입)
좌항의 객체가 우항의 인스턴스 이면 true를 아니면 false 를 리턴한다.

아래처럼 예제를 만들어서 실험해보면서 이해를 해보자.

결과는 위 처럼 instanceof 를 통해 예외상황에 대해서 대비를 하지 않으면 예외가 발생하면서 프로그램이 즉시 종료되는것을 볼 수 있다.




🔗 핵심 정리

클래스 타입 변환 : 다른 클래스 타입으로 객체를 대입하는 것을 말한다.
자동 타입 변환 : 자식 객체를 부모 타입 변수에 대입할 때에는 자동으로 타입이 변환이 된다.
강제 타입 변환 : 자식 객체가 부모 타입으로 변환된 상태에서 다시 원래의 자식 타입으로 변환 하고자 할 때 캐스팅() 연산자를 사용해서 강제 타입 변환할 수 있다.
instanceof 연산자 : 객체가 어떤 타입인지 조사할 때 instanceof 연산자를 사용한다.
주로 강제 타입 변환 전에 변환이 가능한지 조사할 때 사용한다.
다형성 : 객체 사용법은 동일하나 실행결과가 다양하게 나오는 성질을 말한다.
다형성을 구현하는 기술은 메소드 재정의와 타입 변환이 있다.
자식 객체가 재정의된 메소드를 가지고 있을 경우, 부모 타입으로 자동 타입 변환 후에 메소드를 호출하면 재정의된 자식 메소드가 호출 되면서 다양한 실행 결과를 가져올 수 있다.

profile
코린이

0개의 댓글