다형성

  • 하나의 코드가 여러 자료형으로 구현되어 실행되는 것
  • -> 같은 코드에서 여러 다른 실행 결과가 나온다
  • 정보 은닉, 상속과 더불어 OOP의 큰 특징
  • 다형성을 잘 활용하면 유연하고 확장성 있고 유지보수가 편리한 프로그램을 만들 수 있음

다형성의 예

  • 상속을 하면 하위 클래스를 상위 클래스 하나의 타입으로 모두 핸들링할 수 있다
  • 각각 override된 함수에 매개변수로 들어오는 각각의 인스턴스에 맞는 메서드로 호출이 된다
  • 상속한 후 추가한 메서드는 사용할 수 없다, 상위클래스와 하위클래스가 공통적으로 쓰이는 메서드는 호출이 가능하다
class Animal{
    public void move(){
        System.out.println("동물이 움직입니다.");
    }
}

class Human extends Animal{
    @Override
    public void move(){
        System.out.println("사람이 두 발로 걷습니다");
    }

    public void readBook(){
        System.out.println("사람이 책을 읽습니다");
    }
}

class Tiger extends Animal{
    @Override
    public void move(){
        System.out.println("호랑이가 네 발로 걷습니다");
    }

    public void hunting(){
        System.out.println("호랑이가 사냥을 합니다.");
    }
}

class Eagle extends Animal {
    @Override
    public void move() {
        System.out.println("독수리가 하늘을 날아다닙니다.");
    }

    public void flying(){
        System.out.println("독수리가 양날개를 쭉 펴고 날아다닙니다.");
    }
}
public class AnimalTest {

    public static void main(String[] args) {
        Animal hAnimal = new Human();
        Animal tAnimal = new Tiger();
        Animal eAnimal = new Eagle();

        AnimalTest test = new AnimalTest();
        test.moveAnimal(hAnimal);
        test.moveAnimal(tAnimal);
        test.moveAnimal(eAnimal);
    }

    public void moveAnimal(Animal animal){
        animal.move();
    }
}

ArrayList를 사용하면

ArrayList<Animal> animalList = new ArrayList<>();
        animalList.add(hAnimal);
        animalList.add(tAnimal);
        animalList.add(eAnimal);

        for (Animal animal : animalList){
            animal.move();
        }
  • 만약 override하지 않은 메서드를 사용하고 싶다면? (상위 클래스에 없는 메서드)
  • -> 다운캐스팅을 해야한다

다형성을 사용하는 이유

  • 다른 클래스가 추가될 수 있음
  • 확장성 있는 프로그램을 만들 수 있음
  • 사용하지 않을 경우 많은 if-else if 문이 구현되어야 하고 유지보수가 어려워진다..
  • 상위 클래스에서는 공통으로 사용할 부분을 정해놓고 하위클래스에서는 각 클래스에 맞는 기능을 구현한다
  • 여러클래스를 하나의 타입(상위)으로 핸들링할 수 있다!

다형성을 활용한 멤버쉽 프로그램 확장 실습

  • 일반 고객과 VIP 고객 중간 멤버십 만들기
    고객이 늘어 일반 고객보다는 많이 구매하고 VIP보다는 적게 구매하는 고객에게도 해택을 주기로 했다.
    GOLD 고객 등급을 만들고 혜택은 다음과 같다
  1. 제품을 살때는 10프로를 할인해준다
  2. 보너스 포인트는 2%를 적립해준다

GoldCustomer.java

package ch6;

public class GoldCustomer extends Customer{

    double salesRatio;

    public GoldCustomer(int customerID, String customerName) {
        super(customerID, customerName);

        salesRatio = 0.1;
        bonusRatio = 0.02;
        customerGrade = "GOLD";
    }

    public int calcPrice(int price){
        bonusPoint += price * bonusRatio;
        return price - (int)(price * salesRatio);
    }
}

상속받아서 생성자와 calcPrice를 수정해주기만 하면 된다

상속을 사용하는 경우

  • IS - A 관계

    일반적인 개념과 구체적인 개념과의 관계
    상위클래스: 하위보다 일반적인 개념
    하위클래스: 상위보다 구체적인 개념을 더함
    상속은 클래스간의 결합도가 높은 설계
    상위 클래스의 수정으로 하위클래스에 많은 영향을 미칠 수 있다
    계층 구조가 복잡하거나 깊이가 깊으면 좋지 않음

  • HAS - A 관계

    클래스가 다른 클래스를 포함하는 관계
    코드 재사용의 일반적인 방법
    예를 들어 Student가 Subject를 포함하는 관계
    Library를 구현할 때 ArrayList를 생성하여 사용
    상속하지 않음

다운캐스팅

  • 업캐스팅된 클래스를 다시 원래의 타입으로 형 변환
  • 하위 클래스로의 형 변환은 명시적으로 해야함
if (customerE instanceof GoldCustomer) {
            GoldCustomer vc = (GoldCustomer) customerE;
            System.out.println(customerE.showCustomerInfo());
        }

Customer 형으로 업캐스팅된 customerE가 원래 GoldCustomer인지 instanceof로 확인한 후 GoldCustomer로 형 변환을 해줌

public void testDownCasting(ArrayList<Animal> list){

        for (int i = 0; i < list.size(); i++){
            Animal animal = list.get(i);

            if (animal instanceof Human){
                Human human = (Human) animal;
                human.readBook();
            } else if (animal instanceof Tiger) {
                Tiger tiger = (Tiger) animal;
                tiger.hunting();
            } else if (animal instanceof Eagle) {
                Eagle eagle = (Eagle) animal;
                eagle.flying();
            } else {
                System.out.println("unsupported type");
            }
        }
    }

다운캐스팅을 하면 각각의 하위클래스마다 구현된 메서드를 사용할 수 있다

profile
안녕하세요. Chat JooPT입니다.

0개의 댓글