[Ava]8-2型変換過多


プログラムの開発時にインタフェースを使用してメソッドを呼び出しに符号化することで、実装オブジェクトを簡単に、迅速に置き換えることができます.
プログラムソースコードは不変であり,実装オブジェクトを置き換えることでプログラムの実行結果が多様化する,「インタフェースの多形性」である.

自動タイプ変換


オブジェクトをインタフェースタイプに変換することは、自動タイプ変換(Promotion)に相当します.
継承インタフェースインプリメンテーションクラスがサブクラスを作成する場合、サブオブジェクトは自動的にインタフェースタイプに変換することもできます.

自動タイプ変換を使用すると、フィールドの多形性とパラメータの多形性を実現できます.
フィールドとパラメータタイプをインタフェースとして宣言することで、異なるインプリメンテーションオブジェクトを代入でき、実行結果を多様化できます.

フィールドの多形性


第7章では、自動車を例に、タイヤ等級タイプにサブオブジェクトの韓国/錦湖タイヤを代入して交換できることを説明する.
本章では、韓国/錦湖タイヤがタイヤインタフェースを共同で実現しているので、タイヤインタフェースの方法があります.(インタフェースとして使用する代替オブジェクトに適用)
package sec03.exam02;

public interface Tire { //roll() 메소드 호출 방법 설명
	public void roll();
}
package sec03.exam02;

public class HankookTire implements Tire {
	@Override //Tire 인터페이스 구현
	public void roll() {
		System.out.println("한국 타이어가 굴러갑니다.");
	}
}
package sec03.exam02;

public class KumhoTire implements Tire {
	@Override //Tire 인터페이스 구현
	public void roll() {
		System.out.println("금호 타이어가 굴러갑니다.");
	}
}
package sec03.exam02;

public class Car3 {
	
	//인터페이스 타입 필드 선언과 초기 구현 객체 대입
	Tire frontLeftTire = new HankookTire();
	Tire frontRightTire = new HankookTire();
	Tire backLeftTire = new HankookTire();
	Tire backRightTire = new HankookTire();
	
	//인터페이스에서 설명된 roll() 메소드 호출
	void run() {
		frontLeftTire.roll();
		frontRightTire.roll();
		backLeftTire.roll();
		backRightTire.roll();
	}
}
package sec03.exam02;

public class CarExample3 {

	public static void main(String[] args) {
		// TODO 자동 생성된 메소드 스텁
		Car3 myCar=new Car3();
		
		myCar.run();
		
		myCar.frontLeftTire = new KumhoTire();
		myCar.frontRightTire = new KumhoTire();
		
		myCar.run();

	}

}
韓国タイヤが転がっている.
韓国タイヤが転がっている.
韓国タイヤが転がっている.
韓国タイヤが転がっている.
錦湖タイヤが転がっている
錦湖タイヤが転がっている
韓国タイヤが転がっている.
韓国タイヤが転がっている.

パラメータの多形性


自動タイプ変換は、フィールド内の値にも発生しますが、通常はメソッドを呼び出すときに発生します.
7章継承部ではパラメータを親タイプとして宣言し,パラメータの多様化を実現し,呼び出し時にサブオブジェクトを置き換え,今回はパラメータをインタフェースタイプとして宣言し,呼び出し時に実装オブジェクトを置き換える.
パラメータのタイプがインタフェースの場合、どのインプリメンテーションオブジェクトもパラメータとして使用でき、どのインプリメンテーションオブジェクトが提供されるかによって、メソッドの実行結果が異なります.これが「パラメータの多形性」です.
package sec03.exam02;

public interface Vehicle {
	
	public void run();

}
package sec03.exam02;

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

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

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

}
package sec03.exam02;

public class DriverExample {

	public static void main(String[] args) {
		// TODO 자동 생성된 메소드 스텁
		Driver driver = new Driver();
		
		Bus bus = new Bus();
		Taxi taxi = new Taxi();
		
		driver.drive(bus); //자동 타입 변환 : Vehicle vehicle = bus;
		driver.drive(taxi); //자동 타입 변환 : Vehicle vehicle = taxi;

	}

}
バスが走っています.
タクシーが走っています.

強制型変換


インプリメンテーションオブジェクトが自動的にインタフェースタイプに変換される場合、制限条件は、インタフェースで宣言されたメソッドのみが使用可能であることです.
ただし、インプリメンテーションクラスで宣言されたフィールドとメソッドを使用する必要がある場合は、インプリメンテーションクラスのフィールドとメソッドを使用するために、強制タイプ変換(Casting)によってインプリメンテーションクラスタイプに変換することができます.
package sec03.exam02;

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

public class VehicleExample {

	public static void main(String[] args) {
		// TODO 자동 생성된 메소드 스텁
		
		Vehicle vehicle = new Bus();
		
		vehicle.run();
		//vehicle.checkFare(); (x)Vehicle 인터페이스에 checkFare()가 없음
		
		Bus bus = (Bus)vehicle; //강제 타입 변환
		
		bus.run();
		bus.checkFare(); //Bus 클래스에는 checkFare()가 있음

	}

}
バスが走っています.
バスが走っています.
乗車料金を点検する.

オブジェクトタイプのチェック


強制タイプ変換は、オブジェクトがインタフェースタイプに変換されるときに行うことができます.
ただし、どのインプリメンテーションオブジェクトが変換されたのか分からないまま、無計画強制タイプ変換を行うとClassCastExceptionが発生する可能性があります.
たとえば、Taxiオブジェクトがインタフェースに変換された場合、Busタイプに強制的に変換すると、実装クラスのタイプが異なり、エラーが発生します.
Vehicle vehicle = new Taxi();
Bus bus = (Bus) vehicle; //ClassCastException 발생
メソッドのパラメータがインタフェースとして宣言されている場合は、メソッドを呼び出すときに、異なるインプリメンテーションオブジェクトをパラメータとして指定できます.どのインプリメンテーションオブジェクトが指定されているか分からない場合は、強制タイプをBusに変換するとエラーが発生します.
public void drive(Vehicle vehicle){
  Bus bus = (Bus)vehicle; ///ClassCastException 이 발생할 수 있음
  bus.checkFare();
  vehicle.run();
  }
また、インタフェースタイプでは、継承でオブジェクトタイプを決定するために使用されるinstanceof演算子を使用することもできます.
if(vehicle instanceof Bus){
Bus bus = (Bus)vehicle;
}
インタフェースタイプに自動的に変換されるパラメータ値をメソッド内から実装クラスタイプに強制変換する必要がある場合は、instanceof演算子を使用してパラメータがどのオブジェクトであるかを確認し、安全に強制タイプに変換する必要があります.
package sec03.exam02;

public class Driver {
	
	public void drive(Vehicle vehicle) { 
		
		if(vehicle instanceof Bus) { //vehicle 매개 변수가 참조하는 객체가 Bus인지 검사
			Bus bus = (Bus)vehicle; //Bus객체일 경우 안전하게 강제 타입 변환
			bus.checkFare(); //Bus타입으로 강제 타입 변환하는 이유
		}
		vehicle.run();
	}

}
package sec03.exam02;

public class DriverExample {

	public static void main(String[] args) {
		// TODO 자동 생성된 메소드 스텁
		Driver driver = new Driver();
		
		Bus bus = new Bus();
		Taxi taxi = new Taxi();
		
		driver.drive(bus); //자동 타입 변환 : Vehicle vehicle = bus;
		driver.drive(taxi); //자동 타입 변환 : Vehicle vehicle = taxi;

	}

}
乗車料金を点検する.
バスが走っています.
タクシーが走っています.