본문 바로가기
JAVA

[JAVA] 자바 다형성과 instanceof

by IT 정복가 2023. 8. 21.
728x90

다형성이란?

사용방법은 동일하지만 실행 결과가 다양하게 나오는 성질을 말한다.

자동차의 부품을 교환하면 성능이 다르게 나오듯이 객체는 부품과 같아서,

프로그램을 구성하는 객체를 바꾸면 프로그램의 실행 성능이 다르게 나올 수 있다.

다형성을 구성하기 위해서는 자동 타입 변환메소드 재정의가 필요하다. 

 

1. 필드 다형성

필드 다형성은 필드 타입은 동일하지만, 대입되는 객체가 달라져서 실행 결과가 다양하게 나올 수 있는것을 말한다.

 

예제를 통해 알아보자.

class Tire{
	
	public void roll() {
		System.out.println("회전합니다.");
	}
}

class HankookTire extends Tire{
	
	@Override
	public void roll() {
		System.out.println("한국타이어가 회전합니다.");
	}
}

class KumhoTire extends Tire{
	
	@Override
	public void roll() {
		System.out.println("금호타이어가 회전합니다.");
	}
}

class Car{
	public Tire tire;
	
	public void run() {
		tire.roll();
	}
}


public class CarExample {

	public static void main(String[] args) {
		
		//Car 객체 생성
		Car myCar = new Car();
		
		//타이어 객체 장착
		myCar.tire = new Tire();
		myCar.run();
		
		//한국타이어 객체 장착
		myCar.tire = new HankookTire();
		myCar.run();
		
		//금호타이어 객체 장착
		myCar.tire = new KumhoTire();
		myCar.run();
	}

}

Car 클래스에는 Tire 필드가 선언되어 있다. 

메인에서 Car 객체를 생성하고 타이어를 장착하기 위해 다음과 같이 한국타이어, 금호타이어 객체를

Tire 필드에 대입할 수 있다. (자동 타입 변환이 되기 때문에)

 

Car 클래스의 run() 메소드는 tire 필드에 대입된 객체의 roll() 메소드를 호출한다.

만약 HankookTire와 KumhoTire가 roll() 메소드를 재정의하고 있다면, 재정의된 roll() 메소드가 호출된다.

 

<어떤 타이어를 장착했는지에 따라 roll() 메소드의 실행 결과는 달라지게 된다. 이것이 필드의 다형성이다.> 

 


2. 매개변수 다형성

다형성은 필드보다 메소드를 호출할 때 많이 발생한다. 

메소드가 클래스 타입의 매개변수를 가지고 있을 경우,

호출할 때 동일한 타입의 객체를 제공하는 것이 정석이지만

자식 객체를 제공할 수도 있다. 

여기서 다형성이 발생한다!

만약, 어떤 자식 객체가 제공되느냐에 따라 메소드의 실행 결과가 달라진다. 

 

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

Driver라는 클래스가 있고, Vehicle 매개변수를 갖는 drive() 메소드가 정의되어 있다.

drive() 메소드는 매개값으로 전달받은 vehicle의 run() 메소드를 호출한다.

 

여기서 매개값으로 Vehicle 객체만 제공할 수 있는 것은 아니다. 

자동 타입 변환으로 자식 객체도 제공할 수 있다.

 

drive() 메소드는 매개변수 vehicle이 참조하는 객체의 run() 메소드를 호출하는데,

자식 객체가 run() 메소드를 재정의하고 있다면 재정의된 run() 메소드가 호출된다.

그러므로 어떤 자식 객체가 제공되느냐에 따라서 drive()의 실행결과는 달라진다.

 

예제를 통해 알아보자.

class Vehicle{
	
	public void run() {
		System.out.println("차량이 달립니다.");
	}
}

class Bus extends Vehicle{
	
	@Override
	public void run() {
		System.out.println("버스가 달립니다.");
	}
}

class Taxi extends Vehicle{
	
	@Override
	public void run() {
		System.out.println("택시가 달립니다.");
	}
}

class Driver{
	
	//메소드 선언(**클래스 타입의 매개변수를 가지고 있음**)
	public void drive(Vehicle vehicle) {
		vehicle.run();
	}
}
public class DriverExample {

	public static void main(String[] args) {
		
		//Driver 객체 생성
		Driver driver = new Driver();
		
		//매개값으로 Bus 객체를 제공하고 driver() 메소드 호출
		Bus bus = new Bus();
		driver.drive(bus);

		//매개값으로 Taxi 객체를 제공하고 driver() 메소드 호출
		Taxi taxi = new Taxi();
		driver.drive(taxi);
	}

}

 


3. instanceof 연산자

매개변수가 아니더라도 변수가 참조하는 객체의 타입을 확인할 때 instanceof 연산자를 사용한다.

instanceof 연산자에서 좌항의 객체우항의 타입이면 true를 산출하고 그렇지 않으면 false를 산출한다.
public void method(Parent parent){
	if(parent instanceof Child){
    	Child child = (Child) parent;
    }
}
 

*자바12부터는 instanceof 연산의 결과가 true일 경우, 우측 타입 변수를 사용할 수 있기 때문에

강제 타입 변환이 필요없다.

if(parent instanceof Child child){
	//child 변수 사용
}

 

if(parent instanceof Child) {
         Child child = (Child) parent;
}

= (위와 아래는 똑같은 결과이다.)

if(parent instanceof Child child)

 

728x90