다형성

배지원·2022년 9월 27일
0

JAVA

목록 보기
16/32
post-custom-banner

1. 다형성

  • 하나의 객체가 여러 가지 타입을 가질 수 있는 것을 의미한다.
  • 조상 타입 참조 변수로 자손 타입 객체를 다루는 것
  • 자손 타입의 참조변수로 조상 타입의 객체를 가리킬 수 없다.
class Tv{
	int x = 100;
    
    public void power(){
    	System.out.println("Parent");
    }
} 		// 부모
class smartTV extends TV{
	int x = 200;
    
    public void power(){
    	System.out.println("child");
    }
}		// 자식

Tv t = new smartTv();			// (1) 허용
smartTv s = new Tv();			// (2) 불가능
smartTv a = new smartTv();
System.out.println(t.x);		// 100 출력	 형변환을 해도 멤버변수는 참조변수의 타입에 따라 달라짐!!!!
t.power();						// child 출력		오버라이딩이 되었기 때문에
System.out.println(a.x);		// 200 출력
t.power();						// child 출력
- 위처럼 부모 클래스보다 많은 멤버를 가진 자손 클래스는 허용이 가능하지만,
부모보다 적은 멤버를 가진 자손 클래스는 허용이 불가능 하다. 즉, 조상<자손 (가능) / 조상>자손(불가능)

2. 참조변수의 형변환

  • 사용할 수 있는 멤버의 갯수를 조절하는 것
  • 조상 자손 관계의 참조변수는 서로 형변환 가능
  • 자손타입 -> 조상타입 (Up-casting)
  • 조상타입 -> 자손타입 (Down-casting)
class Car{
     String color;
     int door;

     void drive(){
         System.out.println("drive, brrrr~");
     }

     void stop(){
         System.out.println("stop!!!!");
     }

}

class FireEngine extends Car{
    @Override
    void water(){
        System.out.println("water!!!");
    }
}

public class Upcasting {
    public static void main(String[] args) {
        Car c = new Car();
        FireEngine f = new FireEngine();	
        FireEngine f2 = null;

        c = f;      // Car c = (Car)f;    자손 -> 조상
//      c.water();       오류 발생
        f2 = (FireEngine)c;     // 조상타입 -> 자손타입
        f2.water();
    }
}
  • c 객체는 color, door, drive(), stop() 총 4개의 멤버를 사용 가능
  • f 객체는 color, door, drive(), stop(), water() 총 5개의 멤버를 사용가능
  • 따라서, f객체가 4개만 사용하고 싶을때 형변환을 해서 4개만 사용하는 것이다.

3. instanceof 연산자

  • 참조변수의 형변환 가능여부 확인에 사용 가능하면 true 반환
  • 형변환 전에 반드시 instanceof로 확인해야 함
void test(Car c){		
	if(c instanceof FireEngine){			// 형변환이 가능한지 확인
    	FireEngine fe = (FireEngine)c;		// 형변환
        fe.water()


다형성의 장점 및 실습 예제

4. 매개변수의 다형성

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

실습
(1) 부모클래스와 2개의 자식클래스 생성
(2) 메인메서드에서 다형성 실행
- b.buy(new Tv2());
- b.buy(new Computer());
(3) 독립적인 클래스 Buyer의 buy메서드에서 객체형식으로 입력받음 즉, 다형성을 한 객체 2개가 입력됨
(4) price와 bonusPoint를 부모클래스에서 가져와 계산한다
(5) 각 자식 클래스에서 Object의 toString()을 오버라이딩을 했기때문에 매개변수 입력시 오버라이딩 값 출력

class Product{
    int price;
    int bonusPoint;

    Product(int price){
        this.price = price;
        bonusPoint = (int)(price/10.0);     // 제품가격의 10%
    }
}

class Tv2 extends Product{
    Tv2(){
        super(100);     // 조상 클래스의 Product(int price) 호출
    }

    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+"을/를 구입하셨습니다.");
        //  System.out.println(p.toString()+"을/를 구입하셨습니다."); 위에꺼랑 같은의미임
        // 즉, toString()을 위에서 오버라이딩 한 값이 들어감
    }
}

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


        b.buy(new Tv2());               // Product p = new Tv2();
                                        // b.buy(p)                  같은 의미임
        b.buy(new Computer());

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

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

  • 조상타입의 배열에 자손들의 객체를 담을 수 있다.
    예시) 장바구니에 여러 제품들을 넣어야 할때
    장바구니 배열 = (1) Tv;
                         (2) Computer;
                         (3) Audio;
Product[] p = new Product[3];
p[0] = new Tv();
p[1] = new Computer();
p[2] = new Audio();

실습
(1) 위에 실습을 배열을 통해 구현하는 것으로 부모클래스 객체의 배열안에 자손객체를 담는다
(2) 각 클래스에서 개별 객체 생성하여 설계하는 것 보다 가독성이 좋음

class Product2{
    int price;
    int bonusPoint;

    Product2(int price){
        this.price = price;
        bonusPoint = (int)(price/10.0);     // 제품가격의 10%
    }
}

class Tv3 extends Product2{
    Tv3(){
        super(100);     // 조상 클래스의 Product2(int price) 호출
    }

    public String toString(){   // Object클래스의 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;              // Product2 배열에 사용될 카운터

    void buy(Product2 p){
        if(money<p.price){
            System.out.println("잔액이 부족하여 물건을 살 수 없습니다.");
            return;
        }

        money -= p.price;
        bonusPoint += p.bonusPoint;
        item[i++] = p;              // 제품을 Product2[] item에 저장한다.
        System.out.println(p+"을/를 구입하셨습니다.");
        //  System.out.println(p.toString()+"을/를 구입하셨습니다."); 위에꺼랑 같은의미임
        // 즉, toString()을 위에서 오버라이딩 한 값이 들어감
    }

    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 PolyArgumentTestarr {
    public static void main(String[] args) {
        Buyer2 b = new Buyer2();

        b.buy(new Tv3());
        b.buy(new Computer2());
        b.buy(new Audio());
        b.summary();
    }
}
profile
Web Developer
post-custom-banner

0개의 댓글