Java & Kotlin

[Java 객체지향] 다형성

Sue 2022. 1. 31. 21:16

다형성 (Polymorphism)

  • 하나의 코드가 여러 자료형으로 구현되어 실행되는 것
  • 같은 코드에서 다른 실행 결과가 나온다.
  • 정보은닉, 상속과 더불어 객체지향 프로그래밍에서 가장 큰 특징 중 하나이다.
  • 유연하고, 확장성있고, 유지보수가 쉬운 프로그램을 만들 수 있다.
  • 상속, 오버라이딩, 오버라이딩 등을 활용해서 구현할 수 있다.

 

예제 코드

AnimalTest.java
package ch06;

class Animal{	// 상위 클래스
	
	public void move() {
		System.out.println("동물이 움직입니다.");
	}
}

class Human extends Animal{	// 하위 클래스 1
	
	public void move() {
		System.out.println("사람이 두 발로 걷습니다.");
	}
	
	public void readBook() {
		System.out.println("사람이 책을 읽습니다.");
	}
}

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

class Eagle extends Animal{	// 하위 클래스 3 
	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();
		
		hAnimal.move();	// 같은 이름의 메서드 호출 (재정의됨)
		tAnimal.move();
		eAnimal.move();
		
	}

}

 

수행 결과
사람이 두 발로 걷습니다.
호랑이가 네 발로 뜁니다.
독수리가 하늘을 날아다닙니다.

 

다형성을 사용하는 이유

  • 다른 동물을 추가하는 경우 쉽게 클래스를 만들고 메서드만 오버라이딩 해주면 됨
  • 상속과 오버라이딩으로 확장성 있는 프로그램을 구현할 수 있다.
  • 다형성을 사용하지 않는다면 하나의 클래스에 모든 코드를 다 넣어야 한다.
  • 유지보수가 어려워진다.
  • 모든 메서드마다 if-else if 문으로 각 속성에 맞는 기능을 넣어주어야 한다. (추가될때도 마찬가지)
  • 만약 if-else if 문이 있는 메서드가 너무 많다면 클래스 분리를 고려해볼것.
  • 상위 클래스에서는 공통적인 부분을 구현하고 하위 클래스에서는 각 클래스의 기능에 맞는 메서드를 구현하는 것이 좋다.
  • 이럴 경우 여러 클래스를 하나의 타입(상위 클래스)으로 핸들링할 수 있다는 장점이 있다.

 

멤버십 프로그램 확장 - GOLD 등급 회원 만들기

새로운 요구사항이 들어왔다. 일반 고객과 VIP 고객의 중간 멤버십인 GOLD 등급을 만들고 다음과 같은 혜택을 제공한다.

1) 제품을 구입할 때 10% 할인해준다.

2) 보너스 포인트는 2%를 적립해준다.

 

GoldCustomer.java
package ch06;

public class GoldCustomer extends Customer {	// Customer 상속
	
	double salesRatio;	// 할인율 변수 선언

	public GoldCustomer(String customerName, int customerId) {	// 생성자로 상위 클래스의 매개변수와 초기화값 지정
		
		super(customerName, customerId);
		customerGrade = "GOLD";
		bonusRatio = 0.02;
		salesRatio = 0.1;
		
	}
	
	public int calcPrice(int price) {	// Gold Customer의 calcPrice
		bonusPoint += price * bonusRatio;
		return (int)(price * (1-salesRatio));
	}
	

}

 

VIPCustomer.class

상담원 정보를 출력하는 부분 추가

public String showCustomerInfo() {	// showCustomerInfo() 재정의
    return super.showCustomerInfo() + "담당 상담원 번호는 " + agentId + "입니다.";
}

 

CustomerTest.class

Customer 타입(상위 클래스 타입)의 ArrayList를 만들고 하위 클래스의 각 인스턴스를 만들어서 삽입

cost 변수에는 ArrayList에 저장된 각 인스턴스마다 calcPrice() 메서드로 가격을 계산해주는데, 이때 인스턴스마다 다른 가격이 저장된다. (다형성)

package ch06;

import java.util.ArrayList;

public class CustomerTest {

	public static void main(String[] args) {
		
		int price = 10000;
		
		ArrayList<Customer> customerList = new ArrayList<>();	// Customer 타입의 ArrayList 생성
		Customer customerLee = new Customer("Lee",1000);	// 각 타입의 객체 만들기
		Customer customerKim = new VIPCustomer("Kim",10000,"A");
		Customer customerPark = new GoldCustomer("Park",5000);
		
		customerList.add(customerLee);	// ArrayList에 각 객체 넣음
		customerList.add(customerKim);
		customerList.add(customerPark);
		
		for(Customer customer : customerList) {
			
			int cost = customer.calcPrice(price);	// 각 고객이 지불할 가격 저장
			System.out.println(customer.getCustomerName() + "님이 " + cost + "원을 지불하였습니다.");
			System.out.println(customer.showCustomerInfo());
		}
		
	}

}