ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java - 상속과 다형성(다형성)5
    개발언어/JAVA 2023. 11. 1. 16:31

    다형성

    다형성(polymorphism)이란 하나의 코드가 여러 자료형으로 구현되어 실행되는 것을  말한다. 쉽게 말해 같은 코드에서 여러 실행결과가 나오는 것이다.

     

    package polymorphism;
    
        class Mammalia{
           public void move(){
              System.out.println("동물이 움직입니다.");
           }
        }
    
        class Human extends Animal{
            public void move(){
                System.out.println("사람이 두 발로 걷습니다.");
           }
        }
    
        class Tiger extends Animal{
            public void move(){
                System.out.println("호랑이가 네 발로 뜁니다.");
           }
        }
    
    	class Eagle extends Animal{
            public void move(){
                System.out.println("독수리가 하늘을 납니다.");
           }
        }
      
    	public class AnimalTest1{
       		public static void main(String[] args){
            	AnimalTest aTest = new AnimalTest();
                aTest.moveAnimal(new Humna());
                //사람이 두 발로 걷습니다.
                aTest.moveAnimal(new Tiger());
                //호랑이가 네 발로 뜁니다.
                aTest.moveAnimal(new Eagle(());
                //독수리가 하늘을 납니다.
            }
        }
        
        //매개변수의 자료형이 상위 클래스
        public void moveAnimal(Animal animal){
        	//재정의된 메서드 호출
            animal.move();
        }
    }

    위 그림과 같이 3개의 클래스가 포유류 클래스를 상속받는 경우를 생각해 보자.  public 클래스의 멤버 메서드 중하나를 여러개의 하위 클래스로 상속된 상위 클래스 Animal 타입의 매개변수를 받게 한다.  Animal에서 상속받은 하위 클래스가 매개변수로 넘어오면 모두 Animal형으로 변환되고 animal이라는 변수명을 가지게된다. 또한  Animal을 상속한 어떤 하위 클래스의 매개변수가 들어오느냐에 따라 각 하위 클래스에서 각각 다르게 재정의된 move 메서드를 호출하게한다.

     

    가상 메서드 원리에 따라 animal.move()메서드가 호출하는 메서드는 Animal의 move가 아닌 매개변수로 넘어온 실제 인스턴스의 메서드이다. animal.move()코드는 변함이 없지만 어떤 매개변수가 넘어 왔느야에 따라 출력문이 달라진다. 이것이 바로 다형성이다.

     

    다형성의 장점

    다른 동물이 새로 추가되는 경우를 생각해 보자 새로운 동물도 Animal 클래스를 상속받아 구현하면 모든 클래스를 Animal 자료형 하나로 쉽게 관리할 수 있다. 이것이 다형성을 활용한 프로그램의 확장성이다. 각 자료형의 코드가  조금 씩 달라질때 마다 공통되는 부분을 반복해서 구현하면 프로젝트의 전체 코드양이 많아지고 불필요하게 반복되는 생겨나게 된다. 반면에 상위 클래스에서 공통 부분의 메서드를 제공하고, 하위 클래스에서는 그에 기반한 추가 요소를 덧붙여 구현하면 코드 양도 줄어들고 유지보수도 편리해진다. 또 필요에 따라 상속받은 모든 클래스를 하나의 상위 클래스로 처리할 수 있다.  즉 다형성에 의해 각 하위클래스의 여러 가지 구현해 실행할수 있게 되므로 프로그램을 쉽게 확장할 수 있는 것이다. 이처럼 다형성을 잘 활용하면 유연하면서도 구조화된 코드를 구현하여 확장성 있고 유지보수하기 좋은 프로그램을 개발할 수 있는 것이다.

     

    다형성을 활용해 VIP 고객 클래스 완성하기

    Customer.java

    package 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으로 선언
        private void initCustomer(){
        // 멤버 변수의 초기화 부분
         	customerGrade = "SILVER";
            bonusRatio = 0.01;
        }
        
        public int calcPrice(int price){
        	bonusPoin += price*bonusRatio;
            return price;
        }
        
        public String showCustomerInfo(){
        return customerName + "님의 등급은" + customerGrade + "이며, 보너스 포인트는" +
        bonusPoint + "입니다.";
        
        }
        
        ...
    }

    initCustomer()메서드는 Customer 중 고정적인 멤버 변수를 초기화하는데, Customer 클래스를 생성하는 두 생성자에서 공통으로 사용하는 코드로 두번 반복 되기 때문에 메서드로 분리하여 호출한다.

     

    VIPCustomer.java

    package polymorphism;
    
    public class VIPCustomer extends Customer{
       private int agentID;
       double saleRatio;
    	
        public VIPCustomer(int customerID, String customerName, int agentID){
        	super(customerID, customerName);
        	customerGrade = "VIP";
        	bonusRatio = 0.05;
        	saleRatio = 0.1;
        	this.agentID = agentID;  
        }
        
        //지불 가격 메서드 재정의
        public int calcPrice(int price){
        	bonusPoint += price * bonusRatio;
            return price - (int)(price * saleRatio);
        }
        
        //고객 정보 출력 메서드 재정의
        public String showCustomerInfo(){
        	return super.showCustomerInfo() + "담당 상담원 번호는" + agentID + "입니다.";
        }
        
        public int getAgentID(){
        	return agentID;
        }
       
    }

     

    customerTest.java

    package polymorphism;
    
    public class CustomerTest{
    	public static void main(String[] args){
        	Customer customerLee = new Customer();
            customerLee.setCustomerID(10010);
            customerLee.setCustomerName("이준희");
            customerLee.bonusPoin = 1000;
            
            
            //VIPCustomer를 Customer형으로 선언
            Customer customerKim = new VIPCustomer(10020,"김서연",2000);
            customerKim.bonusPoint = 1000;
            
            
            int price = 10000;
            int leePrice = customerLee.calcPrice(price);
            int kimPrice = customerKim.calcPrice(price);
            
            System.out.println(leePrice);
            //10000
            System.out.println(customerLee.showCustomerInfo());
            //이준희 님의 등급은 SIVER이며, 보너스는 포인트는 1100점 입니다.
            System.out.println(kimPrice);
            //9000
        	System.out.println(customerKim.showCustomerInfo());
            //김유신 님의 등급은 VIP이며, 보너스 포인트는 1500점 입니다. 담당 상담원 번호는 
            //12345입니다.
            
        }
    }

    위 코드로 상속 관계에 있는 상위 클래스와 하위 클래스는 같은 상위 클래스 자료형으로 선언되어 생성할 수 있지만 재정의된 메서드는 호출될 뿐만 아니라 이름이 같은 메서드가 서로 다른 역할을 구현하고 있음을 알 수 있다.

     

    [출저 - Do it! 자바 프로그래밍 입문 , 박은종]

    http://www.easyspub.co.kr/20_Menu/BookView/A001/267/PUB

     

    http://www.easyspub.co.kr/20_Menu/BookView/A001/267/PUB

     

    www.easyspub.co.kr

     

    댓글

Designed by Tistory.