본문 바로가기

Study/Java

객체지향 프로그래밍 7장(30강 ~ 35강)

728x90

★다형성(polymorphism)

 - 여러 가지 형태를 가질 수 있는 능력

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

Tv t = new SmartTv(); // 타입 불일치 OK!!

 

객체와 참조 변수의 타입이 일치할 때와 일치하지 않을 때의 차이?

SmartTv s = new SmartTv(); // 참조 변수와 인스턴스의 타입이 일치
Tv t = new SmartTv(); // 조상타입 참조변수로 자손 타입 인스턴스 참조

 SmartTv인스턴스 -> 멤버 7개 모두 사용 가능

SmartTv 인스턴스 -> 멤버는 7개인데 5개 사용가능

 

일부만 사용할 수 있는데 뭐가 장점일까??

 - 일단 차이만 이해하도록 하자.

 

다형성(polymorphism) 특징

- 자손 타입의 참조 변수로 조상 타입의 객체를 가리킬 수 없다.

- 실제 가지고 있는 멤버 개수보다 버튼이 더 많으면 안 됨. 왜? 기능이 없는데 버튼이 있는게 말이 안 되니깐

- 없는 거 호출해서 에러가 난다.

Tv t = new SmartTv(); // OK. 허용
SmartTv s = new Tv(); // 에러. 허용 안 됨.

조상 5개 < 자손 7개 // 쌉가능

자손 7개 < 조상 5개 // 안됨. 없는 거 호출해서 에러남.

 

다형성(polymorphism) 정리

Q. 참조 변수의 타입은 인스턴스의 타입과 반드시 일치해야 하나요?

A. 아닙니다. 일치하는 것이 보통이지만 일치하지 않을 수도 있습니다.


Q. 참조 변수가 조상 타입일 때와 자손 타입일 때의 차이?

A. 참조 변수로 사용할 수 있는 멤버의 개수가 달라집니다.

 

Q. 자손 타입의 참조 변수로 조상 타입의 객체를 가리킬 수 있나요?

A. 아니요, 허용되지 않습니다.

 

참조변수의 형변환

- 사용할 수 있는 멤버의 갯수를 조절하는것, 주소 값, 객체가 바뀌는게 아님

- 조상 자손 관계의 참조변수는 서로 형변환 가능

class Car{
    String color;
    int door;
    
    void drive(){
    	syso("drive, Brrrr~");
    }
	
    void stop(){
    	syso("stop!!!");
    }
}
class FireEngine extends Car{
    void water(){
    	syso("water!!!");
    }
}
FireEngine f = new FireEngine();

Car c = (Car)f;                 //OK. 조상인 Car타입으로 형변환(생략가능)
FireEngine f2 = (FireEngine)c;  //OK. 자손인 FireEngine타입으로 형변환(생략불가)
Ambulance a = (Ambulance)f;     //에러. 상속관게가 아닌 클래스 간의 형변환 불가
참조변수  f의 멤버 개수는 5개이다.
f.color
f.door
f.drive()
f.stop()
f.water()
참조변수 c의 멤버 개수는 4개이다.
c.color
c.door
c.drive()
c.stop()
c.water()
참조변수 f2의 멤버 개수는 5개이다.
f.color
f.door
f.drive()
f.stop()
f.water()
이렇게 참조변수의 형변환을 통해서 멤버 개수를 조절할 수 있다.

- 리모콘을 변경하며 사용할 수 있는 멤버의 개수를 늘렸다 줄였다 할 수 있다.

- 형제 관계 끼린 형변환 할 수 없다.

 

실습예제.

package com.seulgae.ch07;
class CastingTest1 {
	public static void main(String args[]) {
		Car c = new Car(); // Car 멤버가 4개이다. water()가 없다.
		FireEngine fe = (FireEngine)c; // 실제 가르키는 인스턴스가 중요하다.
		// 가르키는 인스턴스의 멤버 개수를 넘어가면 안된다!!
		fe.water(); // 컴파일 오케이, 형변환 실행 에러 java.lang.ClassCastException
	}
}

class Car {
	String color;
	int door;

	void drive() { 		// 운전하는 기능
		System.out.println("drive, Brrrr~");
	}

	void stop() {		// 멈추는 기능	
		System.out.println("stop!!!");	
	}
}

class FireEngine extends Car {	// 소방차
	void water() {		// 물을 뿌리는 기능
		System.out.println("water!!!");
	}
}

 

instanceof 연산자

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

- 형변환 해도 되는지 확인, 어떻게? instanceof 연산자 사용해서

 

Q. 참조변수의 형변환은 왜 하나요?

A. 참조변수(리모콘)을 변경함으로써 사용할 수 있는 멤버의 갯수를 조절하기 위해서

FireEngine f = new FireEngine();
Car c = (Car)f; // 참조변수의 형변환, OK : Car타입으로 형변환(생략가능)

- 값도 그대로, 객체 그대로, 주소값도 그대로, 참조변수의 타입만 달라짐.

 

Q. instanceof 연산자는 언제 사용하나요?

A. 참조변수를 형변환하기 전에 형변환 가능 여부를 확인할때

형변환 확인

 

매개변수의 다형성

- 참조형 매개변수는 메소드 호출시, 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있다.
- 메서드의 매개변수에 조상 타입의  참조 변수를 사용해서 하나의 메서드로 여러 타입의 객체를 받을 수 있음.

 

다형성의 장점 2가지

1. 다형성 매개변수

2. 하나의 배열로 여러종류 객체 다루기.

 

다형성 개념 3가지 정리.

Tv t = new SmartTv(); // 조상 타입의 참조변수로 자손 객체 다루기.
참조변수의 형변환 - 리모콘 바꾸기(사용가능한 멤버갯수 조절)
instanceof 연산자 : 형변환 가능여부 확인

 

 

예제실습.

package com.seulgae.ch07;
class Product {
	int price;			// 제품의 가격
	int bonusPoint;		// 제품구매시 제공하는 보너스 점수

	Product(int price) {
		this.price = price;
		bonusPoint =(int)(price/10.0);	// 보너스 점수는 제품가격의 10%
	}
}

class Tv3 extends Product {
	Tv3() {
		//조상클래스의 생성자 product(int price)를 호출한다.
		super(100);			// Tv의 가격을 100만원으로 한다.
	}

	public String toString() {	// Object클래스의 toString()을 오버라이딩한다.
		return "Tv";
	}
}

class Computer extends Product {
	Computer() {
		super(200);
	}

	public String toString() {
		return "Computer";
	}
}

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.toString()+ "을/를 구입하셨습니다.");
		System.out.println(p+ "을/를 구입하셨습니다.");
	}
}

class PolyArgumentTest {
	public static void main(String args[]) {
		Buyer b = new Buyer();
		
//		Product p = new Tv1();
//		b.buy(p);
		b.buy(new Tv3()); // buy(Product p)
		b.buy(new Computer()); // buy(Product p)

		System.out.println("현재 남은 돈은 " + b.money + "만원입니다.");
		System.out.println("현재 보너스점수는 " + b.bonusPoint + "점입니다.");
	}
}

출력 결과

 

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

- 조상타입의 배열에 자손들의 객체를 담을 수 있다.

 

실습예제.

package com.seulgae.ch07;
class Product2 {
	int price;			// 제품의 가격
	int bonusPoint;		// 제품구매 시 제공하는 보너스점수

	Product2(int price) {
		this.price = price;
		bonusPoint =(int)(price/10.0);
	}

	Product2() {} // 기본 생성자
}
 
class Tv4 extends Product2 {
	Tv4() {
		super(100);	
	}

	public String toString() { return "Tv"; }
}

class Computer2 extends Product2 {
	Computer2() { super(200); }

	public String toString() { return "Computer"; }
}

class Audio extends Product2 {
	Audio() { super(50); }

	public String toString() { return "Audio"; }
}

class Buyer2 {			// 고객, 물건을 사는 사람
	int money = 1000;	// 소유금액
	int bonusPoint = 0;	// 보너스 점수
	Product2[] item = new Product2[10];	// 구입한 제품을 저장하기 위한 배열
	int i =0;			// Product 배열에 사용될 카운터
	
	void buy(Product2 p) {
		if(money < p.price) {
			System.out.println("잔액이 부족하여 무건을 살 수 없습니다.");
			return;
		}

		money -= p.price;	        // 가진 돈에서 구입한 제품의 가격을 뺀다.
		bonusPoint += p.bonusPoint;	// 제품의 보너스 점수를 추가한다.
		item[i++] = p;		        // 제품을 Product[] item을 저장한다.
		System.out.println(p + "을/를 구입하셨습니다.");
	}

	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].toString() + ", ";
//			itemList += item[i] + ", ";
		}
		System.out.println("구입하시니 물품의 총금액은 " + sum + "만원입니다.");
		System.out.println("구입하신 제품은 " + itemList + "입니다.");
	}
}

class PolyArgumentTest2 {
	public static void main(String args[]) {
		Buyer2 b = new Buyer2();

		b.buy(new Tv4());
		b.buy(new Computer2());
		b.buy(new Audio());
		b.summary();
	}
}

출력결과

 

반응형