다형성
하나의 코드가 여러 가지 자료형으로 구현되어 실행되는 것이다.
정보은닉, 상속과 더불어 객체지향 프로그래밍의 가장 큰 개념이다.
다형성 구현하기
하나의 클래스를 상속받은 여러 클래스가 있는 경우
각 클래스마다 같은 이름의 서로 다른 메서드를 재정의 함
상위 클래스 타입으로 선언된 하나의 변수가 여러 인스턴스에 대입되어 다양한 구현이 실행될 수 있음.
3가지의 동물 클래스가 Animal이라는 부모 클래스에게서 상속받은 경우를 프로그래밍해 보자.
package com.kh.polymorphism;
class Animal{
public void move() {
System.out.println("동물이 움직입니다.");
}
}
class Human extends Animal{
@Override
public void move() {
System.out.println("사람이 두 발로 걷습니다.");
}
}
class Tiger extends Animal{
@Override
public void move() {
System.out.println("호랑이가 네 발로 걷습니다.");
}
}
class Eagle extends Animal{
@Override
public void move() {
System.out.println("독수리가 하늘을 납니다.");
}
}
public class AnimalTest {
public static void main(String[] args) {
moveAnimal(new Animal());
moveAnimal(new Human());
moveAnimal(new Tiger());
moveAnimal(new Eagle());
}
public static void moveAnimal(Animal animal) {
animal.move();
}
}
실행 결과
사람이 두 발로 걷습니다.
호랑이가 네 발로 걷습니다.
독수리가 하늘을 납니다.
동물이 움직입니다.
다형성의 장점
상속받은 모든 클래스를 하나의 상위 클래스로 처리할 수 있고 다형성에 의해 각 클래스의 여러 가지 구현을 실행할 수 있으므로 프로그램을 쉽게 확장할 수 있다.
다형성을 잘 활용하면 유연하면서도 구조화된 코드를 구현하여 확장성 있고 유지보수하기 좋은 프로그램을 개발할 수 있다.
상속 파트에서 작성했던 VIP 고객 클래스 완성
package com.kh.polymorphism;
public class Customer {
protected int customerID;
protected String customerName;
protected String customerGrade;
int bonusPoint;
double bonusRatio;
public Customer() {
InitCustomer();
}
public Customer(int customerID, String customerName) {
this.customerID = customerID;
this.customerName = customerName;
InitCustomer();
}
private void InitCustomer() {
customerGrade ="Silver";
bonusRatio = 0.01;
}
public int calcPrice(int price) {
bonusPoint += price * bonusRatio;
return price;
}
public String showCustomerInfo() {
return customerName + " 님의 등급은 "+customerGrade + " 이며, 보너스포인트는 "
+ bonusPoint + "입니다.";
}
...
}
package com.kh.polymorphism;
public class VIPCustomer extends Customer{
private int agentID;
double saleRatio;
//디폴트 생성자 제거하였음. 이제 VIPCustomer 객체 인스턴스 생성할 때 디폴트 생성자 이용 불가.
public VIPCustomer(int customerID, String customerName, int agentID) {
super(customerID, customerName);
customerGrade = "VIP";
bonusRatio = 0.05;
saleRatio = 0.1;
this.agentID = agentID;
}
@Override
public String showCustomerInfo() {
return super.showCustomerInfo() + "담당 상담원의 아이디는 "+this.agentID+ " 입니다.";
}
@Override
public int calcPrice(int price) {
bonusPoint+=price*bonusRatio;
return price - (int)(price * saleRatio);
}
public int getAgentID() {
return agentID;
}
}
package com.kh.polymorphism;
public class CustomerTest {
public static void main(String[] args) {
Customer customerLee = new Customer(); //Customer클래스에서 정의한 디폴트 생성자 사용
customerLee.setCustomerID(10010);
customerLee.setCustomerName("이순신");
customerLee.bonusPoint = 1000;
System.out.println(customerLee.showCustomerInfo());
VIPCustomer customerKim = new VIPCustomer(10020,"김유신",12345);
customerKim.bonusPoint = 1000;
System.out.println(customerKim.showCustomerInfo());
System.out.println("=================할인율과 보너스 포인트 계산================");
int price = 10000;
int leePrice = customerLee.calcPrice(price);
int KimPrice = customerKim.calcPrice(price);
System.out.println(customerLee.getCustomerName()+" 님이 "+leePrice+"원 지불하셨습니다.");
System.out.println(customerLee.showCustomerInfo());
System.out.println(customerKim.getCustomerName()+" 님이 "+KimPrice+"원 지불하셨습니다.");
System.out.println(customerKim.showCustomerInfo());
System.out.println("=================================");
System.out.println();
}
}
실행 결과
이순신 님의 등급은 Silver 이며, 보너스포인트는 1000입니다.
김유신 님의 등급은 VIP 이며, 보너스포인트는 1000입니다.담당 상담원의 아이디는 12345 입니다.
=================할인율과 보너스 포인트 계산================
이순신 님이 10000원 지불하셨습니다.
이순신 님의 등급은 Silver 이며, 보너스포인트는 1100입니다.
김유신 님이 9000원 지불하셨습니다.
김유신 님의 등급은 VIP 이며, 보너스포인트는 1500입니다.담당 상담원의 아이디는 12345 입니다.
=================================
customerLee와 customerKim은 모두 Customer형으로 선언되었고 고객의 자료형은 Customer로 동일하지만, 할인율과 보너스 포인트는 각 인스턴스의 메소드에 맞게 계산되었다. 즉 상속 관계에 있는 상위 클래스와 하위 클래스는 같은 상위 클래스 자료형으로 선언되어 생성할 수 있지만 재정의된 메서드는 각각 호출될 뿐 만 아니라 이름이 같은 메서드가 서로 다른 역할을 구현하고 있음을 알 수 있다.
다운 캐스팅과 instanceof
상위 클래스로 형변환되었던 하위 클래스를 다시 원래 자료형으로 형변환 하는것을 다운 캐스팅이라고 한다.
instanceof는 다운캐스팅을 하기 전에 상위클래스로 형변환된 인스턴스의 원래 자료형을 확인해야 변환 시 오류를 막을 수 있는데 이 때 사용하는 메소드이다.
'교육 | 외부활동 > 이론_JAVA' 카테고리의 다른 글
KH_JAVA_11_인터페이스 (0) | 2022.11.18 |
---|---|
KH자바수업_10_추상 클래스 (2) | 2022.11.17 |
KH자바수업_8_상속 (0) | 2022.11.14 |
KH자바수업_7_다차원 배열, ArrayList (0) | 2022.11.11 |
KH자바수업_6_배열 (0) | 2022.11.10 |