혼자 공부하는 자바 📖/Chapter 08 인터페이스
Chapter 08-2. 타입 변환과 다형성
코이_CO2
2022. 12. 16. 08:56
인터페이스의 다형성
: 프로그램 소스 코드는 변함이 없는데, 구현 객체를 교체함으로써 프로그램의 실행결과가 다양해지는 것
자동 타입 변환
: 프로그램 실행 도중에 자동적으로 타입 변환이 일어나는 것
: 필드의 다형성과 매개 변수의 다형성을 구현 가능
- 구현 객체가 인터페이스 타입으로 변환되는 것은 자동 타입 변환에 해당
- 필드와 매개변수의 타입을 인터페이스로 선언하면 다양한 구현 객체를 대입해서 실행결과를 다양하게 만들 수 있음
필드의 다형성
- 한국 타이어와 금호 타이어는 공통적으로 타이어 인터페이스를 구현
- 둘 다 타이어 인터페이스에 있는 메소드 소유
- 타이어 인터페이스로 동일하게 사용할 수 있는 교체 가능한 객체
- 필드 타입으로 타이어 인터페이스를 선언하면 필드 값으로 한국, 금호 타이어 객체 대입 가능
public class Car {
Tire frontLeftTire = new HankookTire();
Tire frontRightTire = new HankookTire();
Tire backLeftTire = new HankookTire();
Tire backRightTire = new HankookTire();
}
- 타이어 교체 : Car 객체 생성 후, 초기값인 한국타이어 대신 다른 구현 객체 대입 가능
- 어떤 타이어 구현 객체가 저장되어도 Car객체는 타이어 인터페이스에 선언된 메소드만 사용하므로 문제되지 않음
Car myCar = new Car();
myCar.frontLeftTire = new KumhoTire();
myCar.frontRightTire = new KumhoTire();
- Car 객체의 메소드(run)에서 타이어 인터페이스에 선언된 메소드(roll) 호출
void run() {
frontLeftTire.roll();
frontRightTire.roll();
backLeftTire.roll();
backRightTire.roll();
}
- 정리. 필드의 다형성
- frontLeftTire, frontRightTire 교체 전 HankookTire객체 roll() 메소드 호출
- 타이어 교체 후, KumhoTire객체 roll()메소드 호출
- 따라서 Car의 run()메소드를 수정하지 않아도 다양한 roll() 메소드의 실행결과를 얻을 수 있다
매개 변수의 다형성
자동 타입 변환은 주로 메소드를 호출할 때 많이 발생
상속에서는 매개 변수를 부모 타입으로 선언, 호출할 때는 자식 객체를 대입했으나
인터페이스에서는 매개 변수를 인터페이스 타입으로 선언, 호출할 때는 구현 객체를 대입
- Vehicle 타입의 매개 변수가 선언된 Driver 클래스의 drive() 메소드
public class Driver {
public void drive(Vehicle vehicle) {
vehicle.run();
}
}
- Vehicle이 인터페이스 타입일 때
public interface Vehicle {
public void run();
}
- Bus가 구현 클래스라면 Driver의 drive() 메소드를 호출할 때 Bus 객체를 생성하여 매개값을 줄 수 있음
Driver driver = new Driver();
Bus bus = new Bus();
driver.drive(bus);
// 여기서 자동 타입 변환 발생
// Vehicle vehicle = bus;
- Vehicle을 구현한 Bus 객체가 매개값으로 사용되면 자동 타입 변환이 발생(Vehicle vehicle = bus;)
- 매개 변수의 타입이 인터페이스이면, 어떠한 구현 객체도 매개값으로 사용 가능
- 어떤 구현 객체가 제공되냐에 따라 메소드의 실행결과는 다양해지는데 이를 인터페이스 매개 변수의 다형성이라고 한다
강제 타입 변환
- 구현 객체가 인터페이스 타입으로 자동 타입 변환되면, 인터페이스에 선언된 메소드만 사용 가능하는 제약 사항 발생
- 인터페이스 - 3개 메소드, 클래스 - 5개 메소드 -> 인터페이스로 호출 가능한 메소드는 3개
- 경우에 따라 구현 클래스에 선언된 필드와 메소드를 사용해야 할 경우 발생하는데 이때 강제 타입 변환 사용하여 호출
객체 타입 확인
- 강제 타입 변환은 구현 객체가 인터페이스 타입으로 변환되어 있는 상태에서 가능
- 무작정 강제 타입 변환할 경우, ClassCastException 발생 가능
Vehicle vehicle = new Taxi(); // Taxi 객체가 인터페이스로 변환되어 있는 상태
Bus bus = (Bus) vehicle; // Bus 타입으로 강제 타입 변환 시 구현 클래스 타입이 다름
// ClassCastException 오류 발생!
- 메소드의 매개 변수가 인터페이스로 선언된 경우, 메소드를 호출할 때 다양한 구현 객체들을 매개값으로 지정 가능
- 구현 객체에 따라 ClassCastException 발생 가능
- 어떤 구현 객체가 인터페이스 타입으로 변환되었는지 확인하는 방법
- instanceof 연산자 사용 (상속에서도 사용했지만 인터페이스 타입에서도 사용 가능)
- Vehicle 인터페이스 타입으로 변환된 객체가 Bus인지 확인
if(vehicle instanceof Bus) {
Bus bus = (Bus) vehicle;
}
- 인터페이스 타입으로 자동 타입 변환된 매개값을 다시 구현 클래스 타입으로 강제 변환할 경우
- 반드시 어떤 객체인지 instanceof 연산자로 확인
public class Driver {
public void drive(Vehicle vehicle) {
if(vehicle instanceof Bus) { // vehicle 매개 변수가 참조하는 객체가 Bus인지 조사
Bus bus = (Bus) vehicle; // Bus 객체일 경우 안전하게 강제 타입 변환
bus.checkFare(); // Bus 타입으로 강제 타입 변환을 하는 이유
}
vehicle.run();
}
}
인터페이스 상속
- 인터페이스는 클래스와 달리 다중 상속을 허용
- extends 키워드 뒤에 상속할 인터페이스를 나열
public interface 하위인터페이스 extends 상위인터페이스1, 상위인터페이스2 {...}