[기본 개념] 2 | (5.3) 매개변수의 다형성, 객체를 배열로

728x90

[기본 개념] 2 | (5.3) 매개변수의 다형성, 객체를 배열로

1 다형성이란?

2 참조변수의 형변환

3 instanceof연산자

4 참조변수와 인스턴스의 연결

5> 매개변수의 다형성

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

5. 매개변수의 다형성

 참조변수의 다형적인 특징은 메서드의 매개변수에도 적용된다. 아래와 같이 Product, Tv, Computer, Audio, Buyer클래스가 정의되어 있다고 가정하자.

 

        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 ;    // 보너스점수

        }

 

 Buyer클래스에 물건을 구입하는 기능의 메서드를 추가해보자. 구입할 대상이 필요하므로 매개변수로 구입할 제품을 넘겨받아야 한다.

 

        viod buy(Computer c) {

            money = money - c.price ;

            bonusPoint = bonusPoint + c.bonusPoint ;

        }

 

        viod buy(Audio a) {

            money = money - a.price ;

            bonusPoint = bonusPoint + a.bonusPoint ;

        }

 

 이렇게 되면 제품의 종류가 늘어날 때마다 Buyer클래스에 새로운 buy메서드를 추가해야 할 것이다. 그러나 매개변수에 자형성을 적용하면 아래와 같이 하나의 메서드로 간단히 나타낼 수 있다.

 

        viod buy(Product p) {

            money = money - p.price ;

            bonusPoint = bonusPoint + p.bonusPoint ;

        }

 

 Tv클래스와 Computer클래스는 Product클래스의 자손이므로 buy(Product p)메서드에 매개변수로 Tv인스턴스와 Computer인스턴스를 제공하는 것이 가능하다.

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

 조상타입의 참조변수로 자손타입의 객체를 참조하는 것이 가능하므로, Product클래스가 Tv, Computer, Audio클래스의 조상일 때, 다음과 같이 할 수 있는 것을 이미 배웠다.

 

        Product p1 = new Tv( ) ;

        Product p2 = new Computer( ) ;

        Product p3 = new Audio( ) ;

 

위의 코드를 Product타입의 참조변수 배열로 처리하면 아래와 같다.

 

        Product p[ ] = new Product[3] ;

        p[0] = new Tv( ) ;

        p[1] = new Computer( ) ;

        p[3] = new Audio( ) ;

 

이처럼 조상타입의 참조변수 배열을 사용하면 공통의 조상을 가진 객체를 배열로 묶어서 다룰 수 있다.

 

 이때 Product배열의 크기를 10으로 했다면 11개 이상의 제품을 구입할 수 없는 것이 문제다. 그렇다고 해서 배열의 크기를 무조건 크게 설정할 수만도 없다. 이런 경우 Vector클래스를 사용하면 된다.

 

Vector클래스는 동적으로 크기가 관리되는 객체배열이다.

 

매서드 / 생성자 설명
Vector( ) 10개의 객체를 저장할 수 있는 Vector인스턴스를 생성한다.
10개 이상의 인스턴스가 저장되면, 자동적으로 크기가 증가된다.
boolean add(Object o) Vector에 객체를 추가한다. 추가에 성공하면 결과값으로 true, 실패하면 false를 반환한다.
boolean remove(Object o) Vector에 저장되어 있는 객체를 제거한다. 제거에 성공하면 true, 실패하면 false를 반환한다.
boolean isEmpty( ) Vector가 비어있는지 검사한다. 비어있으면 true, 비어있지 않으면 false를 반환한다.
Object get(int index) 지정된 위치(index)의 객체를 반환한다. 반환타입이 Object타입이므로 적절한 타입으로의 형변환이 필요하다.
int size( ) Vector에 저장된 객체의 개수를 반환한다.

 

예제/PolyArgumentTest3.java

import java.util.*;     // Vector클래스를 사용하기 위해

public class PolyArgumentTest3 {
    public static void main(String[] args) {
        Buyer b = new Buyer();
        Tv tv = new Tv();
        Computer com = new Computer();
        Audio audio = new Audio();

        b.buy(tv);
        b.buy(com);
        b.buy(audio);
        b.summary();
        System.out.println();
        b.refund(com);
        b.summary();
    }
}

class Product {
    int price;          // 제품의 가격
    int bonusPoint;     // 제품구매 시 제공되는 보너스점수

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

    Product() {
        price = 0;
        bonusPoint = 0;
    }
}

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;             // 보너스점수
    Vector item = new Vector();     // 구입한 제품을 저장하는데 사용될 Vector객체

    void buy(Product p) {
        if(money < p.price) {
            System.out.println("잔액이 부족하여 물건을 살 수 없습니다.");
            return;
        }
        money -= p.price;           // 가진돈에서 구입한 제품의 가격을 뺀다.
        bonusPoint += p.bonusPoint; // 제품의 보너스 점수를 추가한다.
        item.add(p);                // 구입한 제품을 Vector에 저장한다.
        System.out.println(p + "을/를 구입하셨습니다.");
    }

    void refund(Product p) {        // 구입한 제품을 환불한다.
        if(item.remove(p)) {        // 제품을 Vector에서 제거한다.
            money += p.price;
            bonusPoint -= p.bonusPoint;
            System.out.println(p + "을/를 반품하셨습니다.");
        } else {                    // 제거에 실패한 경우
            System.out.println("구입하신 제품 중 해당 제품이 없습니다.");
        }
    }

    void summary() {                // 구매한 물품에 대한 정보를 요약해서 보여준다.
        int sum = 0;                // 구입한 물품의 가격합계
        String itemList = "";       // 구입한 물품목록

        if (item.isEmpty()) {       // Vector가 비어있는지 확인한다.
            System.out.println("구입하신 제품이 없습니다.");
            return;
        }

        // 반복문을 이용해서 구입한 물품의 총 가격과 목록을 만든다.
        for(int i = 0; i < item.size(); i++) {
            Product p = (Product)item.get(i);
            sum += p.price;
            itemList += (i==0) ? "" + p : ", " + p;
        }
        System.out.println("구입하신 물품의 총 금액은 " + sum + "만원입니다.");
        System.out.println("구입하신 제품은 " + itemList + "입니다.");
    }
}
실행결과

Tv을/를 구입하셨습니다.
Computer을/를 구입하셨습니다.
Audio을/를 구입하셨습니다.
구입하신 물품의 총 금액은 350만원입니다.
구입하신 제품은 Tv, Computer, Audio입니다.

Computer을/를 반품하셨습니다.
구입하신 물품의 총 금액은 150만원입니다.
구입하신 제품은 Tv, Audio입니다.

 

 

 

 

 

출처 | Java의 정석 (남궁 성)

728x90