일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- Matrix
- Binary Search
- 자바
- java
- Math
- Class
- Data Structure
- simulation
- string
- SQL
- Counting
- Stack
- greedy
- Binary Tree
- 코테
- sorting
- geometry
- database
- bit manipulation
- dynamic programming
- two pointers
- Method
- 코딩테스트
- array
- hash table
- Number Theory
- implement
- Tree
- 파이썬
- 구현
- Today
- Total
코린이의 소소한 공부노트
다형성의 장점 본문
지금까지 다형성에 대해 공부한 것은 다음과 같다.
1. 조상 타입의 참조변수에 자손 타입의 객체를 선언할 수 있다.
class Parent { }
class Child extends Parent { }
Parent p = new Child();
2. 참조변수의 형변환: 사용 가능한 멤버 개수 조절
class Parent { } // 멤버 3개
class Child extends Parent { } // 멤버 2개 + 상속 3개 = 총 5개
Parent p = new Child(); // p로 접근 가능한 멤버는 5개 중 3개
Child c = (Child)p; // c로 접근 가능한 멤버는 5개 중 5개
3. instanceof 연산자: 형변환 가능 여부 확인
class Parent { }
class Child1 extends Parent { }
class Child2 extends Parent { }
Parent p = new Parent();
Child1 c1 = new Child1();
Child2 c2 = new Child2();
// 조상-자손 관계에서 객체 타입 <= 클래스 타입일 때 true
System.out.println(p instanceof Parent); // true
System.out.println(c1 instanceof Parent); // true
System.out.println(c1 instanceof Child1); // true
System.out.println(c2 instanceof Parent); // true
System.out.println(c2 instanceof Child2); // true
// 조상-자손 관계에서 객체 타입 > 클래스 타입일 때 false
System.out.println(p instanceof Child1); // false
System.out.println(p instanceof Child2); // false
// 조상-자손 관계가 아닐 때 error
System.out.println(c1 instanceof Child2); // error
System.out.println(c2 instanceof Child1); // error
[다형성의 장점]
다형성의 장점은 2가지로 정리할 수 있다. 이를 설명하기 위해 다음 코드를 기본 틀로 사용할 예정이다. Product 클래스에는 멤버 변수가 2개 있고, 이를 상속받은 클래스 3개가 있다. Product를 구매하려는 Buyer 클래스에도 멤버 변수가 2개 있다.
class Product{ // 제품
int price; // 제품 가격
int bonusPoint; // 적립 포인트
}
class Tv extends Product { }
class Computer extends Product { }
class Audio extends Product { }
class Buyer { // 구매자
int money = 1000; // 소지금액
int bonusPoint = 0; // 소유 포인트
}
1. 다형적 매개변수: 참조형 매개변수는 메서드 호출 시 자신과 같은 타입 또는 자손 타입의 인스턴스를 넘겨줄 수 있다.
이 상태에서 Buyer 클래스에 각 물건을 사는 buy라는 메서드를 만들고 싶다. 다형성을 이용하지 않는다면 아래와 같이 오버로딩을 이용해야 한다.
// Buyer 클래스 내부
void buy (Tv t){
money -= t.price;
bonusPoint += t.bonusPoint;
}
void buy (Computer c){
money -= c.price;
bonusPoint += c.bonusPoint;
}
void buy (Audio a){
money -= a.price;
bonusPoint += a.bonusPoint;
}
// 메인 내부
Buyer b = new Buyer();
Tv t = new Tv();
Computer c = new Computer();
Audio a = new Audio();
b.buy(t);
b.buy(c);
b.buy(a);
너무나도 불편한 일이다. 새 물건 클래스가 생기면 buy 메서드를 또 추가해야 한다. 하지만 우린 다형성을 배웠기 때문에 더 이상 이렇게 하지 않아도 된다.
// Buyer 클래스 내부
void buy (Product p){
money -= p.price;
bonusPoint += p.bonusPoint;
}
// 메인 내부
Buyer b = new Buyer();
Product p1 = new Tv();
Product p2 = new Computer();
Product p3 = new Audio();
b.buy(p1);
b.buy(p2);
b.buy(p3);
다형성으로 인해 조상 타입의 참조변수가 자손 타입의 객체를 가리킬 수 있기 때문에 위와 같이 buy 메서드를 간단하게 만들 수 있게 되는 것이다. 물건 클래스가 또 생겨도 buy 메서드를 추가할 필요가 없다.
위 코드를 좀 더 정리해서 실제로 사용해보면 아래와 같다. 다소 기니 천천히 읽어보자.
class Product{ // 제품
int price; // 제품 가격
int bonusPoint; // 적립 포인트
Product(int price) { // 생성자
this.price = price;
bonusPoint = (int)(price/10.0); // 포인트 = 제품가격의 10%
}
}
class Tv extends Product {
Tv() { // 조상클래스의 생성자 Product(int price)를 호출
super(100); // Tv는 100만원
}
// Object클래스의 toString() 오버라이딩
public String toString() { return "Tv"; }
}
class Computer extends Product {
Computer() {
super(200); // Computer는 200만원
}
public String toString() { return "Computer"; }
}
class Audio extends Product {
Audio() {
super(50); // Audio는 50만원
}
public String toString() { return "Audio"; }
}
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() + "을/를 구입하셨습니다."); // 과 같음
}
}
// 메인 내부
Buyer b = new Buyer();
// 현재 1000만원, 적립 포인트 0점
b.buy(new Tv()); // 이렇게 사용하면 메인에서는 Tv나 Computer 객체에 접근할 수 없지만
// "Tv을/를 구입하셨습니다."
b.buy(new Computer()); // 메서드에서는 접근 가능
// "Computer을/를 구입하셨습니다."
System.out.println("현재 남은 돈은 " + b.money + "만원입니다.");
// "현재 남은 돈은 700만원입니다."
System.out.println("현재 보너스점수는 " + b.bonusPoint + "점입니다.");
// "현재 보너스점수는 30점입니다."
2. 하나의 배열로 여려 종류의 객체 다루기: 조상 타입의 배열에 자손 타입의 객체를 담을 수 있다.
위의 코드에서 보면 Product 타입의 참조 변수에 자손 객체를 담는 코드가 있었다.
Product p1 = new Tv();
Product p2 = new Computer();
Product p3 = new Audio();
이것을 배열로 표현하면 다음과 같다.
Product p[] = new Product[3];
p[0] = new Tv();
p[1] = new Computer();
p[2] = new Audio();
얼핏 보면 코드만 길어진 거 같은데 뭐가 좋을까라는 생각이 들지만, 아래 코드를 보면 생각이 바뀔 것이다.
class Buyer { // 구매자
int money = 1000; // 소지금액
int bonusPoint = 0; // 소유 포인트
Product[] cart = new Product[10]; // 10개까지 담을 수 있는 카트
int i=0; // cart 인덱스
void buy (Product p){
if(money < p.price) {
System.out.println("잔액이 부족합니다.");
return;
}
if(i>=10){
System.out.println("카트가 다 찼습니다.");
return;
}
money -= p.price;
bonusPoint += p.bonusPoint;
cart[i++] = p; // p를 cart에 담고 인덱스 증가시킴
System.out.println(p + "을/를 구입하셨습니다.");
}
}
Buyer 클래스에 물건을 10개까지 담을 수 있는 카트를 만들었다. 이렇게 해놓으면 다른 물건을 사도 cart 배열에 다 담을 수 있게 된다. 만약 다형성을 이용하지 않는다면 물건별로 따로 배열을 관리해야 할 것이다. 이렇게 구매 목록이 관리가 되니 영수증 출력도 가능해진다.
// Buyer 클래스 내부
void bill() { // 영수증 출력
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 + "입니다.");
System.out.println("현재 포인트는 " + bonusPoint + "점 입니다.");
}
// 메인 내부
Buyer b = new Buyer();
// 현재 1000만원, 적립 포인트 0점
b.buy(new Tv()); // "Tv을/를 구입하셨습니다."
b.buy(new Computer()); // "Computer을/를 구입하셨습니다."
b.bill();
// "구입하신 물품의 총금액은 300만원입니다."
// "구입하신 제품은 Tv, Computer, 입니다."
// "현재 포인트는 30점 입니다."
b.buy(new Audio()); // "Audio을/를 구입하셨습니다."
b.bill();
// "구입하신 물품의 총금액은 350만원입니다."
// "구입하신 제품은 Tv, Computer, Audio, 입니다."
// "현재 포인트는 35점 입니다."
[쿠키글] Vector 클래스
Vector 클래스는 가변 배열 기능이 있는 클래스이다.
- 클래스 내부에는 Object 타입의 배열이 있는데, Object 클래스는 모든 클래스의 조상이기 때문에 이 배열에는 모든 타입의 객체를 저장할 수 있다.
- 또한 가변 배열인 만큼 우리가 배열의 크기를 신경 쓰지 않아도 알아서 조절이 된다는 장점이 있다.
'Java' 카테고리의 다른 글
추상 클래스 작성하기 (0) | 2022.05.11 |
---|---|
추상 클래스, 추상 메서드 (0) | 2022.05.05 |
instanceof 연산자 (0) | 2022.05.03 |
참조변수의 형변환 (0) | 2022.04.20 |
다형성 (0) | 2022.04.19 |