5 minute read

Updated:

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

  • 메서드를 호출할 경우, 참조변수 타입에 관계없이 항상 오버라이딩된 메서드가 호출된다.
  • 멤버변수로 호출할 경우, 참조변수의 타입에 따라 달라진다.
  • 즉 멤버변수가 조상클래스와 자손클래스에 중복 정의된 경우 조상타입의 참조변수를 사용했을 때는 조상 클래스에 선언된 멤버변수가 사용되고, 자손타입의 멤버변수를 사용했을 때는 자손 클래스에 선언된 멤버변수가 선언된다.
public class BindingTest
{
    public static void main(String[] args)
    {
        Parent p = new Child();
        Child c = new Child();

        System.out.println("p.x=" + p.x);
        p.method();
        System.out.println("c.x=" + c.x);
        c.method();
    }
}

class Parent {
    int x = 100;

    void method() {
        System.out.println("Parent Method");
    }
}

class Child extends Parent {
    int x = 200;

    void method() {
        System.out.println("Child Method");
    }
}

        // 실행결과
        p.x=100
        Child Method
        c.x=200
        Child Method
  • 이처럼 인스턴스 변수에 직접 접근하면 참조변수의 타입에 따라 사용되는 인스턴스 변수가 달라질 수 있다.
  • 따라서 멤버변수들을 주로 private으로 접근을 제한하고, 외부에서는 메서드를 통해서만 멤버변수에 접근할 수 있도록 해야한다.

매개변수의 다형성

  • 조상타입의 참조변수를 매개변수로 선언하면, 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있다.
  • 아래의 예는 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 클래스에 물건을 구입하는 기능 Buy 메서드를 추가했을 때, 구입할 제품이 필요하므로 매개변수에 구입할 제품을 넘겨받아야 한다. 제품의 종류가 늘어날 때마다 Buy메서드는 계속 추가되어야 한다.
void buy(Computer c) {
    money = money - c.price;
    bonusPoint = bonusPoint + c.bonusPoint;
}
void buy(Tv t) {
    money = money - t.price;
    bonusPoint = bonusPoint + t.bonusPoint;
}
  • 그러나 메서드의 매겨변수에 다형성을 적용하면 하나의 메서드로 간단히 처리할 수 있다.
void buy(Product p) {  
    money = money - p.price;
    bonusPoint = bonusPoint + p.bonusPoint;
}
  • 예제 전체 코드
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); }

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

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

        b.buy(new Tv());
        b.buy(new Computer());

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

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

  • 조상타입의 배열을 사용하면 자손들의 객체를 한번에 담을 수 있다.
  • Product클래스가 Tv, Computer, Audio 클래스의 조상일 때, 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();
  • 앞선 Buyer클래스에 구입한 제품을 저장하기 위한 Product 배열을 추가하면, 구입한 제품을 하나의 배열로 간단히 다룰 수 있다.
class Buyer {               // 고객, 물건을 사는 사람
    int money = 1000;       // 소유금액
    int bonusPoint = 0;     // 보너스 점수
    Product[] item = new Product[10];  // 구입한 제품을 저장하기 위한 배열
    int i = 0;   // Product 배열에 사용될 카운터

    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 + "을/를 구입하셨습니다.");
    }
}
  • 예제 전체 코드
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); }

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

class Buyer {               // 고객, 물건을 사는 사람
int money = 1000;       // 소유금액
int bonusPoint = 0;     // 보너스 점수
Product [] item = new Product[10];  // 구입한 제품을 저장하기 위한 배열
int i = 0;   // Product 배열에 사용될 카운터

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

    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 + "입니다.");

    }
}

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

        b.buy(new Tv());
        b.buy(new Computer());
        b.summary();
    }
}

java.uti.Vector

  • 배열의 크기를 10개 이상 담아야 할 경우, Vector클래스를 사용하면 크기에 제한없이 모든 종류의 객체를 저장할 수 있다.
  • Vector 클래스는 내부적으로 Object타입의 배열을 가지고 있기 때문
// 크기가 10인 product 배열
Product[] cart = new Product[10];
//...

void buy(Product p) {
    //...
        cart[i++] = p;
}
// vector 클래스로 배열 선언
Vector cart = new Vectro();
//...

void buy(Product p) {
    //...
        cart.add(p);
}
// vector 클래스를 이용한 메서드
void summary() {            // 구매한 물품에 대한 정보를 요약해서 보여 준다.
        int sum = 0;            // 구입한 물품의 가격합계
        String itemList = "";      // 구입한 물품목록

        if(item.isEmpty()){     //boolean isEmpty()
            System.out.println("구입하신 제품이 없습니다.");
            return;
        }

        // 반복문을 이용해서 구입한 물품의 총 가격과 목록을 만든다.
        for(int i = 0; i <item.size(); i++) {
            Product p = (Product)item.get(i);   // Vertor의 i번째에 있는 객체를 얻어온다.(Object get(int index) : 형변환 필요)
            sum += p.price;
            itemList += (i==0) ? "" + p : ", " + p;
        }
        System.out.println("구입하는 물품의 총금액은 " + sum + "만원입니다.");
        System.out.println("구입하신 제품은은 " + itemList + "입니다.");

Tags:

Categories:

Updated: