컴퓨터공학 💻 도서관📚
Part2. 3-6 다형성과 다형성을 사용하는 이유 본문
* 다형성(polymorphism)이란
하나의 코드가 형변환(업캐스팅)을 통해서 여러 자료형으로 구현되어 실행되는 것
같은 코드에서 여러 다른 실행 결과가 나옴
정보은닉, 상속과 더불어 객체지향 프로그래밍의 가장 큰 특징 중 하나임
다형성을 잘 활용하면 유연하고 확장성있고, 유지보수가 편리한 프로그램을 만들수 있음
원래는 Java 파일 하나에 클래스 하나를 많이 만드는데 클래스가 여러 개 들어갈 수 도 있다
Java 파일 하나에 public 클래스는 한 개이다
moveAnimal() 메서드의 매개변수의 자료형은 Animal 이고, 들어가는 객체들의 자료형은 하위 클래스인 human, tiger, eagle 이어서 자동으로 형변환(업캐스팅)이 된다
코드는 한 줄인데 어떤 데이터 형이 들어갔느냐에 따라,
어떤 인스턴스 형이 들어갔느냐에 따라 moveAnimal 메서드의 implementation (실행) 이 달라진다 --> 이게 바로 다형성
형 변환은 컴파일 타임 타입 검사에만 영향을 준다
메서드 호출은 참조변수의 타입(Animal)이 아니라, 실제 객체의 타입(생성자의 인스턴스형)에 따라 결정된다.
밑에 3개의 인스턴스 변수의 타입은 모두 Animal 이지만, 생성자의 인스턴스형은 각각 다르다
Animal hAnimal = new Human(); // 형변환(업캐스팅)
Animal tAnimal = new Tiger(); // 자료형은 Animal이지만 생성자는 하위 클래스 생성자
Animal eAnimal = new Eagle();
hAnimal.move(); --> Human 클래스의 move() 메서드 호출
tAnimal.move(); --> Tiger 클래스의 move() 메서드 호출
eAnimal.move(); --> Eagle 클래스의 move() 메서드 호출
상속을 하게 되면 하위 클래스들을 상위 클래스 하나의 타입으로 모두 핸들링할 수 가 있다
이런 것을 클래스 간의 결합도가 굉장히 타이트해진다고 말한다
moveAnimal() 메서드의 매개변수인 animal 변수는 자료형이 Animal 클래스이기 때문에
하위 클래스인 human 클래스의 readBook() 메서드나 tiger 클래스의 hunting() 메서드는 호출할 수 없다
호출하고 싶으면 하위 클래스로 형변환하는 다운 캐스팅을 해야 한다. (다운 캐스팅은 이후 강의에서)
class Animal{ // 상위 클래스 Animal
public void move() {
System.out.println("동물이 움직입니다.");
}
public void eating() {
}
}
class Human extends Animal{ // 하위 클래스 1 Human
public void move() {
System.out.println("사람이 두발로 걷습니다.");
}
public void readBooks() {
System.out.println("사람이 책을 읽습니다.");
}
}
class Tiger extends Animal{ // 하위 클래스 2 Tiger
public void move() {
System.out.println("호랑이가 네 발로 뜁니다.");
}
public void hunting() {
System.out.println("호랑이가 사냥을 합니다.");
}
}
class Eagle extends Animal{ // 하위 클래스 3 Eagle
public void move() {
System.out.println("독수리가 하늘을 날아갑니다.");
}
public void flying() {
System.out.println("독수리가 날개를 쭉 펴고 멀리 날아갑니다");
}
}
public class AnimalTest { // public 클래스는 Java파일에 1개 있어야 한다
public static void main(String[] args) {
Animal hAnimal = new Human(); // 형변환
Animal tAnimal = new Tiger(); // 자료형은 Animal이지만 생성자는 하위 클래스 생성자
Animal eAnimal = new Eagle();
AnimalTest test = new AnimalTest();
test.moveAnimal(hAnimal);
test.moveAnimal(tAnimal);
test.moveAnimal(eAnimal);
// 객체 배열을 위해 만들어진 ArrayList 활용
ArrayList<Animal> animalList = new ArrayList<Animal>();
animalList.add(hAnimal);
animalList.add(tAnimal);
animalList.add(eAnimal);
for(Animal animal : animalList) { // 향상된 for문
animal.move(); // 다형성 : 같은 코드에서 여러 다른 실행 결과가 나온다
}
}
public void moveAnimal(Animal animal) {
animal.move();
}
}
실행결과:
* 다형성을 사용하는 이유
상속과 메서드 재정의를 활용하여 확장성 있는 프로그램을 만들 수 있다
그렇지 않는 경우 메서드마다 많은 if-else if문이 구현되고 코드의 유지보수가 어려워짐
상위 클래스에서는 공통적인 부분을 제공하고 하위 클래스에서는 각 클래스에 맞는 기능 구현
여러 클래스를 하나의 타입(상위 클래스)으로 핸들링 할 수 있음
상속을 할 때 상속의 깊이를 너무 깊게 하는 것은 좋지 않다.
ArrayList 는 넣은 순서대로 출력이 된다
public class GoldCustomer extends Customer{ // Gold 등급 추가
double saleRatio;
public GoldCustomer(int customerID, String customerName){
super(customerID, customerName);
customerGrade = "GOLD";
bonusRatio = 0.02; // Gold 등급은 2%
saleRatio = 0.1;
}
public int calcPrice(int price){
bonusPoint += price * bonusRatio; // Gold 등급의 비율은 2%
return price - (int)(price * saleRatio);
}
}
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); // ArrayList 에 추가
customerList.add(customerShin);
customerList.add(customerHong);
customerList.add(customerYul);
customerList.add(customerKim);
System.out.println("====== 고객 정보 출력 =======");
for( Customer customer : customerList){ // 향상된 for문
System.out.println(customer.showCustomerInfo());
}
System.out.println("====== 할인율과 보너스 포인트 계산 =======");
int price = 10000;
for( Customer customer : customerList){
int cost = customer.calcPrice(price); // calcprice 메서드 사용
System.out.println(customer.getCustomerName() +" 님이 " + + cost + "원 지불하셨습니다.");
System.out.println(customer.getCustomerName() +" 님의 현재 보너스 포인트는 " + customer.bonusPoint + "점입니다.");
}
}
}
'✅🌲강의 복습 노트 > 패캠 JavaSpring 강의,코드 복습' 카테고리의 다른 글
Part2. 3-8 다운 캐스팅과 instanceof (0) | 2025.06.05 |
---|---|
Part2. 3-7 상속은 언제 사용 할까? (0) | 2025.06.05 |
Part2. 3-5 메서드 재정의와 가상 메서드 원리 (0) | 2025.05.23 |
Part2. 3-4 메서드 재정의하기 (overriding) (1) | 2025.05.22 |
Part2. 3-3 상속에서 클래스 생성 과정과 형 변환(업캐스팅) (0) | 2025.05.22 |