Claire's Study Note

08-2. 타입 변환과 다형성

by Hi.Claire
반응형

📓 혼자 공부하는 자바 (신용권, 한빛미디어)

 

08. 인터페이스

08-2. 타입 변환과 다형성

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

상속은 같은 종류의 하위 클래스를 만드는 기술이고, 인터페이스는 사용 방법이 동일한 클래스를 만드는 기술이라는 차이가 있지만, 둘 다 다형성을 구현하는 방법은 비슷하다.

 

인터페이스의 다형성

프로그램을 개발할 때 인터페이스를 사용해서 메소드를 호출하도록 코딩하면 구현 객체를 매우 손쉽고 빠르게 교체할 수 있다.

이처럼 프로그램 소스 코드는 변함이 없는데 구현 객체를 교체함으로써 프로그램의 실행 결과가 다양해지도록 한 것이 인터페이스의 다형성이다.

 

08-2-1. 자동 타입 변환

구현 객체가 인터페이스 타입으로 변환되는 것은 자동 타입 변환이다.

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

 

인터페이스 구현 클래스를 상속해서 자식 클래스를 만들었다면 자식 객체 역시 인터페이스 타입으로 자동 타입 변환할 수 있다.

필드와 매개 변수를 인터페이스 타입으로 선언하면 다양한 구현 객체를 대입해서 실행결과를 다양하게 만들 수 있다.

 

08-2-2. 필드의 다형성

객체를 설계할 때 필드 타입으로 인터페이스를 선언하면 필드값으로 다양한 인터페이스 구현 객체를 대입할 수 있다.

자동 타입 변환이 일어나기 때문에 아무런 문제가 없다.

인터페이스 구현 객체는 인터페이스에 있는 메소드를 모두 가지고 있기 때문에 인터페이스와 사용 방법이 동일하다.

 

예시1. 인터페이스

public interface Tire {

    public void roll();
}

 

예시2. 구현 클래스1 - HankookTire

public class HankookTire implements Tire {

    @Override
    public void roll() {
        System.out.println("한국 타이어가 굴러갑니다.");
    }
}

 

예시3. 구현 클래스2 - KumhoTire

public class KumhoTire implements Tire {

    @Override
    public void roll() {
        System.out.println("금호 타이어가 굴러갑니다.");
    }
}

 

예시4. 필드의 다형성

public class Car {

    Tire frontLeftTire = new HankookTire();
    Tire frontRightTire = new HankookTire();
    Tire backLeftTire = new HankookTire();
    Tire backRightTire = new HankookTire();
    
    void run() {
        frontLeftTire.roll();
        frontRightTire.roll();
        backLeftTire.roll();
        backRightTire.roll();
    }
}

 

예시5. 필드의 다형성 테스트

public class CarExample {

    public static void main(String[] args) {

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

한국 타이어가 굴러갑니다.

한국 타이어가 굴러갑니다.

한국 타이어가 굴러갑니다.

한국 타이어가 굴러갑니다.

금호 타이어가 굴러갑니다.

금호 타이어가 굴러갑니다.

한국 타이어가 굴러갑니다.

한국 타이어가 굴러갑니다.

 

08-2-3. 매개 변수의 다형성

메소드의 매개 변수 타입을 인터페이스로 선언하면 메소드 호출 시 매개값으로 여러 가지 종류의 구현 객체를 줄 수 있기 때문에 메소드의 실행결과가 다양하게 나온다. 이것이 인터페이스의 매개 변수의 다형성이다.

 

예시1. 매개 변수의 인터페이스화

public class Driver {

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

 

예시2. 인터페이스

public interface Vehicle {

    public void run();
}

 

예시3. 구현 클래스1 - Bus

public class Bus implements Vehicle {

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

 

예시4. 구현 클래스2 - Taxi

public class Taxi implements Vehicle {

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

 

예시5. 매개 변수의 다형성 테스트

public class DriverExample {

    public static void main(String[] args) {

        Driver driver = new Driver();
        
        driver.drive(new Bus());
        driver.drive(new Taxi());
    }
}

 

버스가 달립니다.

택시가 달립니다.

 

08-2-4. 강제 타입 변환

구현 객체가 인터페이스 타입으로 자동 타입 변환하면 인터페이스에 선언된 메소드만 사용 가능하다는 제약 사항이 따른다.

만약 구현 클래스에 선언된 필드와 메소드를 사용해야 할 경우에는 강제 타입 변환을 해서 다시 구현 클래스 타입으로 변환한 다음, 구현 클래스의 필드와 메소드를 사용할 수 있다.

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

 

예시1. 인터페이스

public interface Vehicle {

    public void run();
}

 

예시2. 구현 클래스 - Bus

public class Bus implements Vehicle {

    @Override
    public void run() {
        System.out.println("버스가 달립니다.");
    }
    
    public void checkFare() {
        System.out.println("승차 요금을 체크합니다.");
    }
}

 

예시3. 강제 타입 변환

public class VehicleExample {

    public static void main(String[] args) {

        Vehicle vehicle = new Bus(); // 자동 타입 변환
        
        vehicle.run();
        //vehicle.checkFare();
        
        Bus bus = (Bus) vehicle; // 강제 타입 변환
        
        bus.run();
        bus.checkFare();
    }
}

버스가 달립니다.

버스가 달립니다.

승차 요금을 체크합니다.

 

08-2-5. 객체 타입 확인

강제 타입 변환은 구현 객체가 인터페이스 타입으로 변환되어 있는 상태에서만 가능하다.

따라서 어떤 구현 객체가 변환되어 있는지 알 수 없는 상태에서 무작정 강제 타입 변환할 경우 ClassCastException이 발생할 수도 있다.

이때 instanceof 연산자를 사용하면 어떤 구현 객체가 인터페이스 타입으로 변환되었는지 확인할 수 있다.

 

예시1. 객체 타입 확인

public class Driver {

    public void drive(Vehicle vehicle) {


        if(vehicle instanceof Bus) {
            Bus bus = (Bus) vehicle;
            bus.checkFare();
        }

        vehicle.run();
    }
}

 

예시2. 객체 타입 확인 테스트

public class DriverExample {

    public static void main(String[] args) {

        Driver driver = new Driver();
        
        driver.drive(new Bus());
        driver.drive(new Taxi());
    }
}

승차 요금을 체크합니다.

버스가 달립니다.

택시가 달립니다.

 

08-2-6. 인터페이스 상속

인터페이스도 다른 인터페이스를 상속할 수 있다.

인터페이스는 클래스와 달리 다중 상속을 허용한다.

public interface 하위인터페이스 extends 상위인터페이스1, 상위인터페이스2 { ... }

 

하위 인터페이스를 구현하는 클래스는 하위 인터페이스의 메소드뿐만 아니라 상위 인터페이스의 모든 추상 메소드에 대한 실체 메소드를 가지고 있어야 한다.

그렇기 때문에 구현 클래스로부터 객체를 생성한 후에 하위 및 상위 인터페이스 타입으로 변환이 가능하다.

하위 인터페이스로 타입 변환이 되면 하위 및 상위 인터페이스에 선언된 모든 메소드를 사용할 수 있다.

상위 인터페이스로 타입 변환이 되면 상위 인터페이스에 선언된 메소드만 사용 가능하다.

 

예시1. 상위 인터페이스1

public interface InterfaceA {

    public void methodA();
}

 

예시2. 상위 인터페이스2

public interface InterfaceB {

    public void methodB();
}

 

예시3. 하위 인터페이스

public interface InterfaceC extends InterfaceA, InterfaceB {

    public void methodC();
}

 

예시4. 하위 인터페이스 구현

public class ImplementationC implements InterfaceC {

    public void methodA() {
        System.out.println("ImplementationC-methodA() 실행");
    }
    
    public void methodB() {
        System.out.println("ImplementationC-methodB() 실행");
    }
    
    public void methodC() {
        System.out.println("ImplementationC-methodC() 실행");
    }
}

 

예시5. 호출 가능 메소드

public class Example {

    public static void main(String[] args) {

        ImplementationC impl = new ImplementationC();
        
        InterfaceA ia = impl;
        ia.methodA();
        System.out.println();
        
        InterfaceB ib = impl;
        ib.methodB();
        System.out.println();
        
        InterfaceC ic = impl;
        ic.methodA();
        ic.methodB();
        ic.methodC();
    }
}

ImplementationC-methodA() 실행

 

ImplementationC-methodB() 실행

 

ImplementationC-methodA() 실행

ImplementationC-methodB() 실행

ImplementationC-methodC() 실행

반응형

'☕️ Java > 혼자 공부하는 자바' 카테고리의 다른 글

08-1. 인터페이스  (0) 2023.09.24
07-3. 추상 클래스  (0) 2023.09.24
07-2. 타입 변환과 다형성  (1) 2023.09.23
07-1. 상속  (0) 2023.09.18
06-6. 패키지와 접근 제한자  (0) 2023.09.17

블로그의 정보

Claire's Study Note

Hi.Claire

활동하기