Java

[Java] 다형성 / 다운 캐스팅

인생은단짠단짠 2022. 9. 23. 16:14

 

다형성(polymorphism) 이란?

 

 

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

 

 

다형성을 볼 수 있는 코드

class Animal{
	
	public void move() {
		System.out.println("동물이 움직입니다.");
	}
	
	public void eating() {
		
	}
}

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

class Tiger extends Animal{
	
	public void move() {
		System.out.println("호랑이가 네 발로 뜁니다.");
	}
	
	public void hunting() {
		System.out.println("호랑이가 사냥을 합니다.");
	}
}


class Eagle extends Animal{
	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);
		
		ArrayList<Animal> animalList = new ArrayList<Animal>();
		animalList.add(hAnimal);
		animalList.add(tAnimal);
		animalList.add(eAnimal);
		
		for(Animal animal : animalList) {
			animal.move();
		}
	}	
	
	public void moveAnimal(Animal animal) {
		animal.move();
		
	}
}

 

다른 클래스들이 동일한 타입인 것 처럼 쓰이지만 실제적인 implementation은 각각 나타날 수 있습니다.

 

 

다형성을 사용하는 이유?

 

다른 동물을 추가해야 할때 상속과 메서드 재정의를 활용하여 확장성 있는 프로그램을 만들 수 있습니다.

그렇게 하지 않으면 아래 그림처럼 아주 많은 if - else if 문이 구현되고 코드의 유지보수가 어려워집니다.

 

상위 클래스에서는 공통적인 부분을 제공하고, 하위 클래스에서는 각 클래스에 맞는 기능을 구현합니다.

여러 글래스를 하나의 타입( 상위 클래스 )로 핸들링할 수 있습니다.

 

확장성, 유지보수, 여러클래스를 하나의 타입으로 핸들링

 

Customer 예제 활용

public class CustomerTest {

	public static void main(String[] args) {
		
		ArrayList<Customer> customerList = new ArrayList<Customer>();
		
		Customer customerLee = new Customer(10010, "이순신");
		Customer customerShin = new Customer(10020, "신사임당");
		Customer customerHong = new GoldCustomer(10030, "홍길동");
		Customer customerYul = new GoldCustomer(10040, "이율곡");
		Customer customerKim = new VIPCustomer(10050, "김유신", 12345);
		
		customerList.add(customerLee);
		customerList.add(customerShin);
		customerList.add(customerHong);
		customerList.add(customerYul);
		customerList.add(customerKim);
		
		System.out.println("====== 고객 정보 출력 =======");
		
		for( Customer customer : customerList){
			System.out.println(customer.showCustomerInfo());
		}
		
		System.out.println("====== 할인율과 보너스 포인트 계산 =======");
		
		int price = 10000;
		for( Customer customer : customerList){
			int cost = customer.calcPrice(price);
			System.out.println(customer.getCustomerName() +" 님이 " +  + cost + "원 지불하셨습니다.");
			System.out.println(customer.getCustomerName() +" 님의 현재 보너스 포인트는 " + customer.bonusPoint + "점입니다.");
		}
	}
}

 

 

 

 

 

다운 캐스팅

 

업캐스팅 된 클래스를 다시 원래의 타입으로 형 변환 하는 것입니다.

하위 클래스로의 형 변환은 명시적으로 해야 합니다.

Customer vc = new VIPCustomer();              //묵시적
VIPCustomer vCustomer = (VIPCustomer)vc;      //명시적

instatnceof

원래 이 타입의 인스턴스 였는지 확인하여 맞으면 true, 아니면 false를 반환합니다. 

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.readBooks();
        }
        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("error");
        }

    }
}

 

그런데 다운 캐스팅을 하면 코드가 더러워집니다.

그래서 할 수 있으면 오버라이딩을 해서 사용하는게 코드가 깔끔합니다.

그러나 반드시 원래타입으로 되돌려야 한다면 instanceof로 체크 후 다운캐스팅 해줍니다. 

 

 

'Java' 카테고리의 다른 글

[Java] 자료구조  (0) 2022.10.01
[Java] 컬렉션 프레임워크  (0) 2022.10.01
[Java] 상속  (1) 2022.09.23
[Java] Random값 생성  (0) 2022.09.22
[Java] this  (0) 2022.09.21