본문 바로가기
멀티캠퍼스 풀스택 과정/Java의 정석

자바의 정석3-6 instanceof 연산자, 다형성의 장점(1,2)

by 이쟝 2022. 1. 5.

instanceof 연산자

- 참조변수의 형변환 가능여부 확인에 사용. 형변환이 가능하면 true로 반환

- 형 변환 전에 반드시 instanceof로 확인하고 형 변환 해야함!

- instanceof연산자의 구조: 참조변수 instanceof 타입(클래스명)

 

-> 인스턴스의 원래 기능을 모두 사용하려고 형변환을 하는데 Car타입의 참조변수(리모컨)인 c로는 Water( )를 호출할 수 없으니까 참조변수(리모컨)를 FireEngine타입으로 바꿔서 water( )를 호출함!

 

void doWork(Car c) {  // new Car(), new FireEngine(), new Ambulance() 모두 가능
	if(c instanceof FireEngine) {		// 1) 형변환이 가능한지 확인
		FireEngine fe = (FireEngine)c;       // 2) 형변환
	}else if(c instanceof Ambulance) {
		Ambulance a = (Ambulance)c;     
}

FireEngine fe = new FireEngine();                // FireEngine 객체 생성
System.out.println(fe instanceof Object);       // true
System.out.println(fe instanceof Car);          // true
System.out.println(fe instanceof FireEngine);  // true

 

Object obj = (Object)fe;  // ok 자손 -> 조상
Car c = fe;                // ok 자손 -> 조상

-> 자기자신도 참이 나오지만 상속계층(조상)도 true가 나옴!

 

-> 어떤 타입에 대한 instanceof연산의 결과가 true -> 검사한 타입으로 형변환이 가능하다는 것을 뜻함


매개변수의 다형성(다형성의 장점1)

- 메서드의 매개변수로 조상타입의 참조변수를 사용해 하나의 메소드로 자손타입의 객체를 받을 수 있다.

 

다형성?(기억안나면 3-5 다시보기)

1) Tv t = new SmartTv( ) 조상타입의 매개변수로 자손타입의 객체를 다루기

2) 참조변수의 형변환 – 사용가능한 멤버개수를 조절하기 위해서 참조변수의 값을 바꾸기

3) instanceof 연산자 – 형변환 가능여부 확인

 

- 참조형 매개변수는 메서드 호출 시, 자신과 같은 타입 또는 자손타입 인스턴스를 넘겨줄 수 있다.

 

예제) Product, Tv, Computer, buy가 정의되어 있다. 

 

class Product { // 부모
	int price;   // 제품의 가격
	int bonusPoint;   // 제품구매시 제공하는 보너스 점수
	
	Product(int price) {  // Product 생성자 생성
		this.price = price; 
		bonusPoint = (int)(price/10.0);  // 보너스점수는 제품가격의 10%)
	}
}

class Tv extends Product {  // 자손
	Tv(int price) {
		// 조상클래스의 생성자 Product(int price)를 호출한다.
		super(price);     // Tv의 가격을 정한다. 
	}
	// Object클래스의 toString()을 오버라이딩한다.
	public String toString() { return "Tv"; }
	
} 
class Computer extends Product {  // 자손
	Computer(int price) { 
		super(price);  
	}
	// Object클래스의 toString()을 오버라이딩한다.
	public String toString() { return "Computer"; }
}

class Buyer{             // 고객, 물건을 사는 사람
	int money = 1000;    // 소유금액
    int bonusPoint = 0;  // 보너스점수
}

 

Buyer클래스에 물건을 구입하는 기능의 메서드를 추가하기

 

class Buyer { // 고객, 물건을 사는 사람
	int money = 1000;   // 소유금액
	int bonusPoint = 0; // 보너스점수
	
	void buy(Product p) {
		if(money < p.price) {
			System.out.println("잔액이 부족해 물건을 살 수 없습니다.");
			return;
		}
		money -= p.price;    // 가진돈에서 구입한 제품의 가격을 뺀다.
		bonusPoint = p.bonusPoint;   // 제품의 보너스 점수를 추가한다.
		System.out.println(p + "을/를 구입하셨습니다.");
//		System.out.println(p.toString() + "을/를 구입하셨습니다."); 위 코드와 동일
	}
}

 

더보기
더보기

매개변수가 Product타입의 참조변수라는 것은, 메서드의 매개변수로 Product클래스의 자손타입의 참조변수면 어느것이나 매개변수로 받아들일 수 있다는 것!!

-> 다른 제품 클래스를 추가할 때 Product클래스를 상속받기만 하면, buy(Product)메서드의 매개변수로 받아들여질 수 있다. 

 

		Buyer b = new Buyer();  // Buyer클래스 객체 생성
		
		b.buy(new Tv(100));      // Tv 구매, buy(Product p)
//		Product p = new Tv();  // 위의 코드와 동일(두 줄을 한 줄로)
//		b.buy(p);
		
		b.buy(new Computer(100)); // Computer 구매, buy(Product p)
		
		System.out.println("현재 남은 돈은 " + b.money + "만원입니다.");
		System.out.println("현재 보너스점수는 " + b.bonusPoint + "점입니다.");

 

더보기
더보기

<출력값> 

Tv을/를 구입하셨습니다.
Computer을/를 구입하셨습니다.
현재 남은 돈은 800만원입니다.
현재 보너스점수는 10점입니다.


매개변수의 다형성(다형성의 장점2)

여러종류의 객체를 배열로 다루기

 

-> 조상타입의 참조변수로 자손타입의 객체를 다루는 것 

Product p1 = new Tv( );         // 조상인 product와 자손인 Tv

Product p2 = new Computer( );  // 조상인 product와 자손인 computer

Product p3 = new Audio( );      // 조상인 product와 자손인 audio

 

-> 위의 코드를 Product 타입의 참조변수 배열로

Product p[ ] = new Product[3];

p[0] = new Tv( );

p[1] = new Computer( );

p[2] = new Audio( );

 

-> 조상타입의 참조변수 배열을 사용하면, 공통의 조상을 가진 서로 다른 종류의 객체를 배열로 묶어서 다룰 수 있다. 

 

예제) 위의 Buyer 클래스에 구입한 제품을 저장하기 위한 Product 배열 추가하기

 

class Buyer { // 고객, 물건을 사는 사람
	int money = 1000;   // 소유금액
	int bonusPoint = 0; // 보너스점수
	Product[] item = new Product[10];  // 구입한 제품을 저장하기 위한 배열
	int i = 0;                      // Product배열 item에 사용될 index
	
	void buy(Product p) {
		if(money < p.price) {
			System.out.println("잔액이 부족해 물건을 살 수 없습니다.");
			return;
		}
		
		money -= p.price;            // 가진돈에서 구입한 제품의 가격을 뺀다.
		bonusPoint = p.bonusPoint;   // 제품의 보너스 점수를 추가한다.
		item[i++] = p;               // 제품을 Product[] item에 저장한다. 
		System.out.println(p + "을/를 구입하셨습니다.");
//		System.out.println(p.toString() + "을/를 구입하셨습니다."); 위 코드와 동일
	}
}

 

더보기
더보기

구입한 제품을 담기 위헤 Buyer클래스에 Product배열인 item을 추가했다.

buy메서드에 'item[i++] = p;'문장을 추가해서 물건을 구입하면, 배열 item에 저장되도록 했다.

 

예제) 구매한 물품에 대한 정보를 요약해서 보여주는 summary 메서드 생성! (물품의 가격합계와 물품목록)

 

void summary() { // 구매한 물품에 대한 정보를 요약해서 보여준다. 
		int sum = 0;           // 구매한 물품의 가격 합계
		String itemList = "";  // 구매한 물품목록 
		
		//반복문을 이용해서 구입한 물품의 총 가격과 목록을 만든다.
		for(int i=0;i<item.length;i++) {
			if(item[i]==null) break;
			sum += item[i].price;
			itemList += item[i] + ", ";
		}
		System.out.println("구입하신 물품의 총 금액은 " + sum + "만원입니다.");
		System.out.println("구입하신 물품들은 " + itemList + "입니다. ");
}