Java

다형성 Polymorphism, 유연한 코드 작성을 위한 개념

데브노트 2025. 4. 22. 17:53

⭐다형성
Polymorphism

하나의 데이터 타입을 다양한 형태로 바라볼 수 있다는 개념

한 요소가 여러 형태를 가질 수 있다는 가능성을 가리킨다.

⭐ 다형성의 장점은

부모 타입으로 자식 클래스를 인스턴스화 할 수 있다는 점이다.
이는 자바의 굉장한 기능이다.

다형성을 이해한다면
유연한 코드를 작성할 수 있다.

 

 

예제) 동물 클래스를 인간, 호랑이 클래스가 상속하게 하자

package com.polymorphism;
/**
 * 4.22 3교시 다형성
 */
public class Animal {

    public void move() {
        System.out.println("동물이 움직인다");
    }
    public void eat() {
        System.out.println("동물이 먹는다");
    }

}//end of Animal class

class Human extends Animal { // 상속 관계로 설정... 다형성

    @Override
    public void move() {
        System.out.println("사람이 걷는다");
    }
    @Override
    public void eat() {
        System.out.println("사람이 식사한다");
    }
    public void read() {
        System.out.println("사람이 읽는다");
    }

}//end of Human class

class Tiger extends Animal {

    @Override
    public void move() {
        System.out.println("호랑이가 활보한다");
    }
    public void hunt() {
        System.out.println("호랑이가 사냥한다");
    }

}//end of Tiger class

 

코드 테스트

package com.polymorphism;
/**
 * 4.22 3교시 다형성
 *
 * 다형성
 * 하나의 데이터 타입을 다양한 형태로 바라보는 것
 *
 * 한 메서드(클래스)가 여러 형태를 가질 수 있다.
 * 상속관계를 통해 다형성을 살펴본다.
 */
public class AnimalTest1 {
    //main
    public static void main(String[] args) {

        Animal animal1 = new Animal();
        animal1.move();
        animal1.eat();
        System.out.println();
        /*
        다형성의 장점

        부모 타입으로 자식 클래스를 인스턴스화 할 수 있다.

        이는 자바의 굉장한 기능
         */
        Animal animal2 = new Tiger(); //? 다형성.. 업캐스팅
        animal2.move();
        animal2.eat();
        System.out.println();
        /*
        코드를 작성하는 컴파일 시점
        프로그램을 실행하는 런타임 시점
         */
        Animal animal3 = new Human();
        animal3.move();
        animal3.eat();

    }//end of main
}//end of class

 

코드테스트2

package com.polymorphism;
/**
 * 4.22 3교시 다형성
 */
public class AnimalTest2 {

    //main
    public static void main(String[] args) {

        /*
        다형성
        하나의 메서드가
        여러 형태를 가질 수 있는 능력

        move()

        배열
        하나의 변수에 통으로 데이터를 관리하고 싶다면
         */
        Animal[] animals = new Animal[3];

        animals[0] = new Animal();
        animals[1] = new Tiger();
        animals[2] = new Human();

        for (int i = 0; i < animals.length; i++) {
            animals[i].move();
        }

    }//end of main
}//end of class



⭐업캐스팅 / 다운캐스팅

업캐스팅

부모클래스의 데이터타입으로
자식클래스의 객체를 대입하는 것을 말한다.

이는 자동으로 이뤄진다.

다운캐스팅

부모클래스의 참조변수를
자식클래스의 객체로 

((Banana) fruits[i]).saleBanana();

이 객체가 특정 클래스에 종속됐는지 확인하는 구문

if (fruits[i] instanceof Banana) {}

 

예제)

복숭아, 바나나 클래스를 만들고

부모클래스인 과일 클래스를 만들어보자

 

1. 복숭아 클래스

package com.polymorphism.fruits;
/**
 * 4.22 3_1교시 다형성
 *
 * 과일을 통해
 * 상속
 * 바텀업
 * 업캐스팅
 * 다운캐스팅 이해
 */
public class Peach extends Fruit {

//    String name;
//    int price;

    public Peach() {
        name = "춘식이복숭아";
        price = 5000;

    }

}//end of Peach

 

2. 바나나 클래스

바나나 클래스에는 고유의 멤버변수와 메서드를 넣었다.

package com.polymorphism.fruits;
/**
 * 4.22 3_1교시 다형성
 */
public class Banana extends Fruit {

    String ogrin; // Banana만의 멤버변수

        public Banana() {
            name = "델몬트바나나";
            price = 3000;
            ogrin = "필리핀";
        }

    public void saleBanana() {
        System.out.println("지금은 할인 기간입니다");
        System.out.println("이 방송이 나간 뒤(메서드호출) 바나나 가격을 천원 할인");
        price -= 1000;
    }

}//end of Banana

 

3. 부모클래스인 과일 클래스 설계

package com.polymorphism.fruits;
/**
 * 4.22 3_1교시 다형성
 */
public class Fruit {

    String name;
    int price;

    public Fruit() {
        name = "춘식이복숭아";
        price = 5000;

    }
    public void showInfo() {
        System.out.print("상품명: ");
        System.out.print(name + " ");
        System.out.print("가격: ");
        System.out.println(price + "원");
    }
}//end of Fruits

 

4. 코드 실행부

package com.polymorphism.fruits;
/**
 * 4.22 3_1교시 다형성
 *
 * 업캐스팅
 * 다운캐스팅
 */
public class FruitTest1 {
    //main
    public static void main(String[] args) {

        Fruit fruit1 = new Peach(); //업캐스팅된 상태
        Fruit fruit2 = new Banana();

        fruit1.showInfo();
        fruit2.showInfo();

        System.out.println();
        /*
        바나나의 원산지 정보를 출력하시오

        이 문제는
        컴파일 시점과 런타임 시점을 이해해야 한다.

        업캐스팅된 상태에서는
        컴파일 시점에 부모에 있는 변수나 메서드만 이해 가능
         */
        //fruit2.orign

        String reultOrigin = ((Banana)fruit2).ogrin; // 다운캐스팅
        System.out.println("바나나 원산지: " + reultOrigin);

        System.out.println();
        /*
        인스턴스오브 연산자
        instanceof
        ↳예약어

        다운캐스팅 관련 활용가능한 기능
         */

        if (fruit2 instanceof Banana) { // true
            System.out.println("바나나인가? true");
        }
        if (fruit2 instanceof Peach) { // false
            System.out.println("복숭아인가? true");
        }

        System.out.println();
        /*
        fruit2에 saleBanana() 메서드를 호출하시오
         */

        ((Banana)fruit2).saleBanana(); //다운캐스팅
        fruit2.showInfo();

    }//end of main
}//end of class

 

5. 다운캐스팅 연습을 위한 심화문제

package com.polymorphism.fruits;
/**
 * 4.22 3_1교시 다형성
 *
 * 업캐스팅
 * 다운캐스팅
 */
public class EMart {
    //main
    public static void main(String[] args) {

        Banana banana1 = new Banana();
        Banana banana2 = new Banana();
        /*
        배열
        배열을 사용할 때는
        반드시 크기를 먼저 지정한다.

        배열의 길이와
        요소의 길이는 항상 동일한 것은 아니다.
         */
        Banana[] bananas = new Banana[10];
        bananas[0] = banana1;
        bananas[1] = banana2;

        Peach[] peaches = new Peach[3];
        peaches[0] = new Peach();
        peaches[1] = new Peach();

        System.out.println();
        /*
        다형성
        다형성을 이해한다면
        유연한 코드를 작성할 수 있다.
         */
        Fruit[] fruits = new Fruit[5];
        fruits[0] = new Banana();
        fruits[1] = new Peach();
        fruits[2] = new Banana();
        fruits[3] = new Peach();
        /*
        문제
        배열 안에 들어있는 각각의 객체 showInfo 호출

        데이터타입이 바나나면
        원산지 정보와 세일 메서드를 호출하라
         */
        for (int i = 0; i < fruits.length; i++) {

            if (fruits[i] != null) {

                if (fruits[i] instanceof Banana) {
                    System.out.print((i + 1) + "번 ");
                    fruits[i].showInfo();
                    System.out.println("원산지: " + ((Banana) fruits[i]).ogrin);
                    ((Banana) fruits[i]).saleBanana();
                    System.out.println("===== ===== =====");
                } else {
                    System.out.print((i + 1) + "번 ");
                    fruits[i].showInfo();
                    System.out.println("===== ===== =====");
                }//end of if

            }//defensive

        }//end of for

    }//end of main

}//end of class