ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] Chapter 8.2 인터페이스의 타입 변환과 다형성
    Java 2023. 4. 24. 18:44

    인터페이스 다형성의 개요

    다형성을 구현하기 위해서는 메소드 재정의와 타입 변환이 필요합니다.  상속은 같은 종류의 하위 클래스를 만드는 기술이고, 인터페이스는 사용 방법이 동일한 클래스를 만드는 기술로 다르지만 다형성을 구현하는 방법은 비슷합니다.

    프로그램을 개발할 때 인터페이스를 사용해서 메소드를 호출하도록 코딩하면 구현 객체를 쉽게 교체할 수 있습니다.  이와 같이 인터페이스의 다형성을 사용하면, 프로그램 소스 코드는 변함이 없으면서 구현 객체를 교체함으로써 프로그램의 실행결과가 다양해 집니다.

     

     

    인터페이스의 자동 타입 변환

    인터페이스의 자동 타입 변환은 구현 객체가 인터페이스 타입으로 변환되는 것을 말합니다.  인터페이스 구현 클래스를 상속해서 자식 클래스를 만들었다면 자식 객체 역시 인터페이스 타입으로 자동 타입 변환할 수 있습니다.

    자동 타입 변환을 이용하면 필드의 다형성과 매개 변수의 다형성을 구현할 수 있습니다.  필드와 매개 변수의 타입을 인터페이스로 선언하면 다양한 구현 객체를 대입해서 실행결과를 다양하게 만들 수 있습니다.

    인터페이스 변수 = 구현 객체;

     

     

    필드의 다형성

    서비스 로직을 설계할 때 필드 타입으로 인터페이스를 선언하면 필드값으로 구현 객체를 대입할 수 있습니다. 그리고 앞에서 배웠던 인터페이스의 자동 타입 변환이 일어납니다.

    public class Car {
    	Tire frontLeftTire = new HankookTire();
        Tire frontRightTire = new HankookTire();
        Tire backLeftTire = new HankookTire();
        Tire backRightTire = new HankookTire();
    }

     

    Car 객체를 생성한 후, 초기값으로 대입한 구현 객체 대신 다른 구현 객체를 대입할 수 있습니다.  현실에서는 타이어를 교체하는 것과 같습니다.

    Car myCar = new Car();
    myCar.frontLeftTire = new KumhoTire();
    myCar.frontRightTire = new KumhoTire();

     

    Car 객체의 run() 메소드에서 타이어 인터페이스에 선언된 roll( ) 메소드를 호출합니다.  frontLeftTire와 frontRightTire를 교체하기 전에는 HankookTire 객체의 roll( ) 메소드가 호출되지만, KumhoTire로 교체된 후에는 KumhoTire 객체의 roll( ) 메소드가 호출됩니다.  Car의 run( ) 메소드를 수정하지 않아도 다양한 roll( ) 메소드의 실행결과를 얻을 수 있습니다.  

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

     

    이것을 필드의 다형성이라고 합니다.

     

     

    매개 변수의 다형성

    자동 타입 변환은 필드의 값을 대입할때도 발생하지만, 주로 메소드를 호출할 때 많이 발생합니다.  상속과 비교하자면, 매개값을 다양화하기 위해서 상속에서는 매개 변수를 부모 타입으로 선언하고 호출할 때에는 자식 객체를 대입합니다.

     

    이번에는 매개 변수를 인터페이스 타입으로 선언하고 호출할 때에는 구현 객체를 대입합니다.  매개 변수 타입이 인터페이스일 경우 어떠한 구현 객체도 매개값으로 사용할 수 있고, 어떤 구현 객체가 제공되느냐에 따라 메소드의 실행결과는 다양해질 수 있습니다.

    public interface Vehicle {
    	public void run();
    }
    public class Driver {
    	public void drive(Vehicle vehicle) {  
        // Vehicle vehicle = bus; -> 구현 객체를 대입, 자동 타입 변환
        	vehicle.run();  // 구현 객체의 run( ) 메소드가 실행됩니다.
        }
    }

     

    이것을 인터페이스 매개변수의 다형성이라고 합니다.

     

     

    강제 타입 변환

    경우에 따라서 구현 클래스에 선언된 필드와 메소드를 사용해야 할 경우도 발생합니다.  예를 들어, 인터페이스에는 3개의 메소드가 선언되어 있고 클래스에는 5개의 메소드가 선언되어 있다면, 인터페이스로 호출 가능한 메소드는 3개뿐입니다.

    경우에 따라서는 구현 클래스에 선언된 필드와 메소드를 사용해야 할 경우도 발생합니다.  이때 강제 타입 변환을 해서 다시 구현 클래스 타입으로 변환한 다음, 구현 클래스의 필드와 메소드를 사용할 수 있습니다.

    구현클래스 변수 = (구현클래스) 인터페이스 변수;

     

     

    객체 타입 확인

    강제 타입 변환은 구현 객체가 인터페이스 타입으로 변환되어 있는 상태에서 가능합니다.  현 객체가 변환되어 있는지 알 수 없는 상태에서 무작정 강제 타입 변환할 경우 ClassCastException이 발생할 수 있습니다.  

    어떤 구현 객체가 인터페이스 타입으로 변환되었는지 확인하는 방법이 있습니다.  우리는 상속에서 객체 타입을 확인하기 위해 instanceof 연산자를 사용합니다.  인터페이스 타입으로 자동 타입 변환된 매개값을 메소드 내에서 다시 구현 클래스 타입으로 강제 타입 변환해야 한다면 반드시 매개값 어떤 객체인지 instanceof 연산자로 확인하고 안전하게 강제 타입 변환을 해야 합니다.

    package sec02.exam04;
    
    public class Driver {
    	public void drive(Vehicle vehicle) {
        	if (vehicle instanceof Bus) {
            	Bus bus = (Bus) vehicle;
                bus.checkFare();
             }
             vehicle.run();
        }
    }

     

     

     

    출처 | 혼자 공부하는 자바

Designed by Tistory.