본문 바로가기
Java

자바 클래스 타입 변환과 다형성

by 승환파크 2023. 6. 26.

다형성은 사용 방법은 동일하지만 다양한 객체를 이용해서 다양한 실행결과가 나오도록 하는 성질이다. 예를 들어 자동차가 타이어를 사용하는 방법은 동일하지만 어떤 타이어를 사용(장착)하느냐에 따라 주행 성능이 달라질 수 있다.

 

다형 성을 구현하려면 메소드 재정의와 타입 변환이 필요하다.

 

 

자동 타입 변환

타입 변환이란 타입을 다른 타입으로 변환하는 행위를 말한다. 기본 타입의 변환과 마찬가지로 클래스도 타입 변환이 있다.

클래스의 변환은 상속 관계에 있는 클래스 사이에서 발생 한다. 자식은 부모 타입으로 자동 타입 변환이 가능하다.

 

자동 타입 변환은 프로그램 실행 도중 자동적으로 타입 변환이 일어나는 것을 말한다. 자동 타입 변환은 아래와 같은 조건에서 일어난다.

부모타입 변수 = 자식타입;

 

자동 타입 변환의 개념은 자식과 부모의 특징과 기능을 상속받기 때문에 부모와 동일하게 취급될 수 있다는 것이다. 예를 들어, 고양이가 동물의 특징과 기능을 상속받았다면 '고양이는 동물이다.'가 성립한다.

 

예를 들어 Animal 과 Cat 클래스가 아래와 같이 상속 관계에 있다고 가정해 본다면

public class Animal{
	...
}

public class Cat extendss Animal{
	...
}

Cat 클래스로부터 Cat 객체를 생성하고 이것을 Animal 타입 변수에 대입하면 자동 타입 변환이 일어난다.

Cat cat = new Cat();
Animal animal = cat;

// Animal animal = new Cat(); 도 가능하다.

 

 

필드의 다형성

필드의 타입을 부모 타입으로 선언하면 다양한 자식 객체들이 저장될 수 있기 때문에 필드 사용 결과가 달라질 수 있다. 이것을 필드의 다형성 이라고 한다.

 

예를 들어 자동차를 구성하는 부품은 언제든지 교체할 수 있다. 부품은 고장날 수도 있고, 성능이 더 좋은 부품과 교체를 하기도 한다. 객체 지향 프로그래밍에서도 마찬가지이다. 프로그램은 수많은 객체들이 서로 연결되고 각자의 역할을 하는데, 이 객체들은 다른 객체로 교체될 수 있어야 한다.

 

자동차 클래스에 포함된 타이어 클래스를 생각해보면 자동차 클래스를 처음 설계할 때 사용한 타이어 객체는 언제든지 성능이 좋은 다른 타이어 객체로 교체할 수 있어야 한다. 새로 교체되는 타이어 객체는 기존 타이어와 사용 방법은 동일하지만 실행결과는 더 우수하게 나와야 할 것이다. 이것을 프로그램으로 구현하기 위해서 상속과 재정의, 타입 변환을 이용한다.

 

부모 클래스를 상속하는 자식 클래스는 부모가 가지고 있는 필드와 메소드를 가지고 있으니 사용 방법이 동일할 것이다. 자식 클래스는 부모의 메소드를 재정의해서 메소드의 실행 내용을 변경함으로써 더 우수한 실행 결과가 나오게 할 수 있다. 그리고 자식 타입을 부모 타입으로 변환할 수 있다. 이 세가지 다형성을 구현할 수 있는 기술적 조건이 된다.

 

필드의 다형성은 아래 코드로 살펴볼 수 있다.

class Car{
	// 필드
    Tire frontLeftTire = new Tire();
    Tire frontRightTire = new Tire();
    Tire backLeftTire = new Tire();
    Tire backRightTire = new Tire();
    
    // 메소드
    void run(){
    	...
    }
}

 

Car 클래스는 4개의 Tire 필드를 가지고 있다. Car 클래스로부터 Car 객체를 생성하면 4개의 Tire 필드에 각각 하나씩 Tire 객체가 들어가게 된다. 그런데 frontRightTire 와 backLeftTire 를 HankookTire 와 KumhoTire로 겨체할 이유가 생겼다. 이러한 경우 아래와 같은 코드를 사용해서 교체할 수 있다.

Car myCar = new Car();
myCar.frontRightTire = new HankookTire();
myCar.backLeftTire = new KumhoTire();
myCar.run();

 

Tire 클래스 타입인 frontRightTire 와 backLeftTire는 원래 Tire 객체가 저장되어야 하지만, Tire의 자식 객체가 저장되어도 상관 없다. 왜냐하면 자식 타입은 부모 타입으로 자동 타입 변환이 되기 때문이다. frontRightTire와 backLeftTire에 Tire 자식 객체가 저장되어도 Car 객체는 Tire 클래스에 선언된 필드와 메소드만 사용하므로 전혀 문제가 되지 않는다.  HankookTire 와 KumhoTire는 부모인 Tire의 필드와 메소드를 가지고 있기 때문이다.

 

Car 객체에 run() 메소드가 있고, run() 메소드는 각 Tire 객체의 roll() 메소드를 아래와 같이 호출한다고 가정했을 때

void run(){
	frontLeftTire.roll();
    frontRightTire.roll();
    backLeftTire.roll();
    backRightTire.roll();
}

 

frontRightTire와 backLeftTire를 교체하기 전에는 Tire 객체의 roll() 메소드가 호출되지만, HankookTire 와 KumhoTire로 교체되면 HankookTire 와 KumhoTire 가 roll() 메소드를 재정의하고 있으므로 교체 이후에는 HankookTire 와 KumhoTire 의 roll() 메소드가 호출되어 실행 결과가 달라진다.

 

이와 같이 자동 타입 변환을 이용해서 Tire 피르값을 교체함으로써 Car 의 run() 메소드를 수정하지 않아도 다양한 roll() 메소드의 실행 결과를 얻게 된다. 이것이 바로 필드의 다형성이다.

 

 

매개 변수의 다형성

자동 타입 변환은 필드의 값을 대입할 때에도 발생하지만, 주로 메소드를 호출할 때 많이 발생한다. 메소드를 호출할 때에는 매개 변수의 타입과 동일한 매개값을 지정하는 것이 정석이지만, 매개값을 다양화 하기 위해 매개 변수에 자식 객체를 지정할 수도 있다.

 

 

강제 타입 변환

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

자식타입 변수 = (자식타입)부모타입;

 

예를 들어 아래와 같이 Child 객체가 Parent 타입으로 자동 변환된 상태에서 원래 Child로 강제 변환할 수 있다.

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

 

자식 타입이 부모 타입으로 자동 타입 변환하면, 부모에 선언된 필드와 메소드만 사용 가능하다는 제약 사항이 따른다. 만약 자식에 선언된 필드와 메소드를 꼭 사용해야 한다면 강제 타입 변환을 해서 다시 자식 타입으로 변환한 다음 자식의 필드와 메소드를 사용하면 한다.

 

 

객체 타입 확인

강제 타입 변환은 자식 타입이 부모 타입으로 변환되어 있는 상태에서만 가능하기 때문에 처음부터 부모 타입으로 생성된 객체는 자식 타입으로 변환할 수 없다.

 

이 때 부모 변수가 참조하는 객체가 부모 객체인지 자식 객체인지 확인하고 싶을 때는 어떤 방식으로 처리하냐면 어떤 객체가 어떤 클래스의 인스턴스인지 확인하기 위해 instanceof 연산자를 이용한다.

 

연산자의 좌항에는 객체가 오고 우항에는 타입이 오는데, 좌항의 객체가 우향의 인스턴스이면, 즉 우향의 타입으로 객체가 생성되었다면 true를 리턴하고 그렇지 않으면 false 를 리턴한다.

boolean result = 좌항(객체) instanceof 우항(타입);

'Java' 카테고리의 다른 글

자바 인터페이스  (0) 2023.06.27
자바 추상 클래스  (0) 2023.06.27
자바 상속  (0) 2023.06.26
자바 패키지와 접근 제한자  (0) 2023.06.26
자바 인스턴스 멤버와 정적 멤버  (0) 2023.06.23