profile image

L o a d i n g . . .

강제 타입변환?

부모타입을 자식 타입으로 변환하는 것 (처음부터 부모 타입으로 생성된 객체는 자식 타입으로 변환 불가)

Parent parent = new Child(); //자동 타입 변환
Child child = (Child) parent; //강제 타입 변환

 

부모 변수가 참조하는 객체가 부모 객체인지 자식 객체인지 확인하는 방법

 

instanceof (객체가 어떤 클래스의 인스턴스인지 확인)

boolean result = 좌항(객체) instanceof 우항(타입)
		
public void method(Parent parent) {
	// Parent 매개 변수가 참조하는 객체가 Child인지 조사
	if(parent instanceof Child){
    	Child child = (Child) parent;
    }
}

 

 

 

 

자동 타입변환?

프로그램 실행 도중 자동적으로 타입 변환이 일어남

//자동타입변환 발생
부모타입 변수 = 자식타입;


Cat cat = new Cat();
Animal animal = cat; //Animal animal = new Cat(); 도 가능

 

자식은 부모의 특징과 기능을 상속받기 때문에 부모와 동일하게 취급될 수 있다.

 

 

class A {}

class B extends A {}
class C extends A {}

class D extends B {}

class E extends C {}


public class PromotionEx {
	public static void main(String[] args) {
		B b = new B();
		C c = new C();
		D d = new D();
		E e = new E();
		
		A a1 = b;
		A a2 = c;
		A a3 = d;
		A a4 = e;
		
		B b1 = d;
		C c1 = e;
		
		//B b3 = e;
		//C c2 = d; 상속관계에 있지 않기 때문에 컴파일 에러 발생
	}
}

부모 타입으로 자동 타입 변환된 이후에는 부모 클래스에 선언된 필드와 메소드만 접근이 가능하다.

비록 변수는 자식 객체를 참조하지만, 변수로 접근 가능한 멤버는 부모 클래스 멤버로만 한정된다.

 

그러나 예외가 있는데, 메소드가 자식 클래스에서 재정의되었다면 자식 클래스의 메소드가 대신 호출된다.

 

 

 

 

public class Parent {
	public void method1() {
		System.out.println("Parent-method1()");
	}
	
	public void method2() {
		System.out.println("Parent-method2()");
	}
}
public class Child extends Parent{

	@Override
	public void method2() {
		System.out.println("Child-method2()");
	}

	public void method3() {
		System.out.println("Child-method3()");
	}
}
public class ChildEx {
	public static void main(String[] args) {
		Child child = new Child();
		
		Parent parent = child; //자동 타입 변환
		parent.method1();
		parent.method2();
		//parent.method3(); 호출 불가능
		child.method3();
	}
}

 

부모 클래스를 상속하는 자식 클래스는 부모가 가지고 있는 필드와 메소드를 가지고 있다.

자식 클래스는 부모의 메소드를 재정의해 메소드의 실행 내용을 변경할 수 있다.

자식 타입을 부모 타입으로 변화할 수 있다.

 

 

 

public class Tire {
	public int maxRotation; // 최대 회전 수(타이어 수명)
	public int accumulateRotation; // 누적 회전 수
	public String location; // 타이어의 위치
	
	public Tire (String location, int maxRotation) {
		this.location = location;
		this.maxRotation = maxRotation;
	}
	
	public boolean roll() {
		++accumulateRotation;
		if(accumulateRotation < maxRotation) {
			System.out.println(location + "Tire 수명: " + (maxRotation-accumulateRotation) + "회");
			return true;
		} else {
			System.out.println("*** " + location + "Tire 펑크 ***");
			return false;
		}
	}
}
public class TireCar {
	Tire frontLeftTire = new Tire("앞왼쪽", 6);
	Tire frontRightTire = new Tire("앞오른쪽", 2);
	Tire backLeftTire = new Tire("뒤왼쪽", 3);
	Tire backRightTire = new Tire("뒤오른쪽", 4);
	
	int run() {
		System.out.println("[자동차가 달립니다.]");
		if(frontLeftTire.roll()==false) { stop(); return 1;};
		if(frontRightTire.roll()==false) { stop(); return 2;};
		if(backLeftTire.roll()==false) { stop(); return 3;};
		if(backRightTire.roll()==false) { stop(); return 4;};
		return 0;
	}
	
	void stop () {
		System.out.println("[자동차가 멈춥니다]");
	}
}

모든 타이어를 1회 회전시키기 위해 각 Tire 객체의 roll()메소드를 호출. 

false를 리턴하는 roll()이 있을 경우 stop()메소드를 호출하고 해당 타이어 번호를 리턴

 

 

자식클래스 생성

public class Hankook extends Tire{
	public Hankook(String location, int maxRotation) {
		super(location, maxRotation);
	}

	@Override
	public boolean roll() {
		++accumulateRotation;
		if(accumulateRotation < maxRotation) {
			System.out.println(location + "Hankook Tire 수명: " + (maxRotation-accumulateRotation) + "회");
			return true;
		} else {
			System.out.println("*** " + location + " HanKook Tire 펑크 ***");
			return false;
		}
	}
}
public class Kumho extends Tire{
	public Kumho(String location, int maxRotation) {
		super(location, maxRotation);
	}

	@Override
	public boolean roll() {
		++accumulateRotation;
		if(accumulateRotation < maxRotation) {
			System.out.println(location + "Kumho Tire 수명: " + (maxRotation-accumulateRotation) + "회");
			return true;
		} else {
			System.out.println("*** " + location + " Kumho Tire 펑크 ***");
			return false;
		}
	}
}

 

 

Tire, TireCar, Hankook, Kumho클래스를 이용하는 실행 클래스 작성

public class CarEx {
	public static void main(String[] args) {
		TireCar car = new TireCar();
		
		for (int i = 1; i <= 5; i++) {
			int problemLocation = car.run();
			
			switch (problemLocation) {
			case 1:
				System.out.println("앞왼쪽 HanKookTire로 교체");
				car.frontLeftTire = new Hankook("앞왼쪽", 15);
				break;
			case 2:
				System.out.println("앞오른쪽 KumhoTire로 교체");
				car.frontRightTire = new Kumho("앞오른쪽", 13);
				break;
			case 3:
				System.out.println("뒤왼쪽 HanKookTire로 교체");
				car.backLeftTire = new Hankook("뒤왼쪽", 14);
				break;
			case 4:
				System.out.println("뒤오른쪽 KumhoTire로 교체");
				car.backRightTire = new Kumho("뒤오른쪽", 17);
				break;
			}
			System.out.println("=============================");
		}
	}
}

 

 

 

 

매개변수의 다형성

매개변수의 타입이 클래스일 경우, 해당 클래스의 객체 뿐 아니라 자식 객체까지도 매개값으로 사용할 수 있다

매개값으로 어떤 자식 객체가 제공되느냐에 따라 메소드 실행 결과가 다양해 질 수 있다

자식 객체가 부모의 메소드를 재정의 했다면 메소드 내부에서 재정의된 메소드를 호출함으로써 메소드를 다양하게 사용한다

 

 

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

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

 

 

매개값의 자동 타입 변환과 매소드 재정의를 이용해 매개변수의 다형성 구현

public class DriverEx {
	public static void main(String[] args) {
		Driver driver = new Driver();
		
		Bus bus = new Bus();
		Taxi taxi = new Taxi();
		
		driver.drive(bus);
		driver.drive(taxi);
	}
}

 

 

 

 

 

 

 

 

 

instanceof 예제

public class Dad {
	
}

public class Baby extends Dad{
	
}

 

public class Instanceof {
	public static void method1(Dad dad) {
		// Baby 타입으로 변환이 가능한지 확인
		if(dad instanceof Baby) {
			Baby baby = (Baby) dad;
			System.out.println("method 1 - Baby로 변환 성공");
		} else {
			System.out.println("method 1 - Baby로 변환 실패");
		}
	}
	
	public static void method2(Dad dad) {
		Baby baby = (Baby) dad;
		System.out.println("method 2 - Baby로 변환 성공");
	}
	
	public static void main(String[] args) {
		Dad dad = new Baby();
		method1(dad);
		method2(dad);

		Dad dad2 = new Dad();
		method1(dad2);
		method2(dad2); //ClassCastException 예외 발생
	}
}

 

Instanceof 클래스에서 method1() method2()를 호출할 경우 Baby 객체를 매개값으로 전달하면 두 메소드 모두 예외발생X 

그러나 Dad 객체를 매개값으로 전달하면 method2()에서 ClassCastException이 발생한다.

 

이유는 method1()은 instanceof 연산자로 변환이 가능한지 확인 후 변환을 하지만

method2()는 무조건 변환하려고 했기 때문이다

 

예외가 발생하면 프로그램은 즉시 종료되기 때문에 method1()과 같이 강제 타입 변환 전에는 instanceof 연산자로 변환시킬타입의 객체인지 조사가 필요하다

 

 

 

 

참고:

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

 

 

 

 

너무잠와서 리앵트는 내일해야겠다.. Zzz

반응형

'개발 > JAVA' 카테고리의 다른 글

[Java] 인터페이스(Interface)  (0) 2022.07.12
[Java] 추상(abstract) 클래스  (0) 2022.07.12
[Java] 상속  (0) 2022.07.11
[Java] Getter & Setter  (0) 2022.07.08
[Java] 인스턴스 멤버와 정적 멤버  (0) 2022.07.07
복사했습니다!