본문 바로가기
객체지향 OOP

[자바의정석 기초 객체지향 개념] 다형성

by bzerome240 2022. 5. 30.

chendongshan via Getty Images

다형성 polymorphism (중요!)

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

 

1 조상 타입 참조변수로 자손 타입 인스턴스 참조하기

// 1. 보통 - 참조변수와 인스턴스의 타입이 일치함
SmartTv s = new SmartTv();

// 2. 다형성 - 조상 타입 참조변수로 자손 타입 인스턴스 참조 -> 타입 불일치 -> 에러아님!
Tv t = new SmartTv();

// 3. 자손 타입의 참조변수로 조상 타입의 객체를 가리킬 수 없다. -> 에러
SmartTv st = new Tv();
  1. SmartTv 리모콘으로 SmartTv를 다루면 모든 기능을 사용할 수 있다.
  2. Tv 리모콘 (조상) 으로 SmartTv를 다루면 일부 기능만 사용할 수 있다.
  3. SmartTv 리모콘에있는 일부기능이 Tv에는 없어서 사용할 수 없다 (에러)
💡
Q. 참조 변수의 타입은 인스턴스의 타입과 반드시 일치해야 하는가? A. 아니다. 일치하는 것이 보통이지만 일치하지 않을 수 있다.
Q. 참조 변수가 조상 타입일 때와 자손 타입일 때의 차이점? A. 참조 변수로 사용할 수 있는 멤버의 개수가 달라진다.
Q. 자손 타입의 참조 변수로 조상 타입의 객체를 가리킬 수 있는가? A. 아니다. 허용되지 않는다.

 


 

2 참조변수의 형변환

  • 사용할 수 있는 멤버의 개수를 조절하는 것
  • 조상 자손 관계의 참조변수는 서로 형변환 가능

 

3 형변환 전에는 반드시 instanceof로 확인해야 함

void doWork(Car c) {
	if(c instanceof FireEngine) {    // 1. 형변환이 가능하지 확인
		FireEngine fe = (fireEngine)c; // 2. 형변환
		fe.water();
		...
💡
Q. 참조변수의 형변환은 왜 하는가? A. 참조변수(리모콘)을 변경함으로써 사용할 수 있는 멤버의 개수를 조절하기 위해서
Q. instanceof연산자는 언제 사용하는가? A. 참조변수를 형변환 하기 전에 형변환 가능 여부를 확인할 때

 


 

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

  • 참조형 매개변수는 메서드 호출 시 자신과 같은 타입 또는 자손 타입의 인스턴스를 넘겨줄 수 있다.
class Product {
	int price;

	Product(int price) {
		this.price = price;
	}
}

class Tv extends Product {
	Tv() {
		super(100);
	}

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

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

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

class Buyer {
	int money = 1000;
	
	void buy(Product p) {
		if(money < p.price) {
			return;
		}

		money -= p.price;
		System.out.println(p + "구입"); // p = p.toString
}

class Test {
	public static void main(String args[]) {
		Buyer b = new Buyer();
		b.buy(new Tv()); // buy(Product p) -> TV구입
		b.buy(new Computer()); // buy(Product p) -> Computer구입

		/* 
				b.buy(new Tv)); 문장은 아래와 동일하다

				Buyer b = new Buyer();
				Product p = new Tv();
				b.buy(p);
		*/
	}
}

 


 

다형성 장점 2) 하나의 배열에 여러 종류 객체 저장하기

  • 조상타입의 배열에 자손들의 객체를 담을 수 있다.
Product p[] = new Product(3);
p[0] = new Tv();
p[1] = new Computer();
p[2] = new Audio();

예제

class Product {
	int price;
	int bonusPoint;

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

	Product() {}
}

class Tv extends Product {
	Tv() { super(100); }

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

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

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

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

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

class Buyer {
	int money = 1000;
	int bonusPoint = 0;
	
	Product[] cart = new Product[10];
	int i = 0;

	void buy(Product p) {
		if(money < p.price) { return; }

		money -= p.price;
		bonusPoint += p.bonusPoint;
		cart[i++] = p;
		System.out.println(p+"구입");
	}

	void summary() {
		int sum = 0;
		String itemList = "";

		for(int i=0; i<cart.length; i++) {
			if(cart[i] == null) break;
	
			sum += cart[i].price;
			itemList += cart[i] + ",";
		}

		System.out.println("구입 총 금액: " + sum);
		System.out.println("구입 제품: " + itemList);			
	}
}

class Ex {
	public static void main(String args[]) {
		Buyer b = new Buyer();
	
		b.buy(new Tv());
		b.buy(new Computer());
		b.buy(new Audio());
		b.summary();
	}
}

 

 

728x90
반응형

댓글