컴퓨터공학 💻 도서관📚

Part2. 3-6 다형성과 다형성을 사용하는 이유 본문

✅🌲강의 복습 노트/패캠 JavaSpring 강의,코드 복습

Part2. 3-6 다형성과 다형성을 사용하는 이유

들판속초록풀 2025. 5. 26. 17:42

다형성(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 + "점입니다.");
		}
	}
}
Comments