모든지 기록하자!

[Java] 상속 - 형 변환, super, 생성자 (예제: 고객관리) 본문

Java

[Java] 상속 - 형 변환, super, 생성자 (예제: 고객관리)

홍크 2021. 5. 15. 00:42
728x90

하위 클래스가 생성되는 과정

VIPCustomer customerChoi = new VIPCustomer();
		customerChoi.setCustomerID(10101);
		customerChoi.setCustomerName("최민식");
		customerChoi.bonusPoint = 1000;		
		System.out.println(customerChoi.showCustomerInfo());

 

VIPCustomer 클래스로 선언한 customerChoi 인스턴스는 상위 클래스의 변수를 사용할 수 있다.

이는 그 변수를 저장하고 있는 메모리가 존재한다는 뜻이다.

테스트를 하기 위해 Customer와 VIPCustomer 클래스 생성자에 출력문을 추가해보자.

 

public class Customer {
	
	protected int customerID;
	protected String customerName;
	protected String customerGrade;
	int bonusPoint;
	protected double bonusRatio;
	
	public Customer() {
		customerGrade = "SILVER";
		bonusRatio = 0.01;
		System.out.println("Customer() 생성자 호출");  // 상위 클래스 생성할때 출력문
	}
		
	public int calcPrice(int price){
				
		bonusPoint += price * bonusRatio;		
		return price;
	}
	                  
                //....(이하생략)
	}

Customer() 생성자에 출력문을 넣었다. Customer 인스턴스가 생성되면 이 문장이 출력된다.

그리고 VIPCustomer() 생성자에도 출력문을 추가한다.

 

public class VIPCustomer extends Customer{ 
					 
	private int agentID;
	private double saleRatio;

	public VIPCustomer() {
   	customerGrade = "VIP"; 
     	bonusRatio = 0.05;     
     	saleRatio = 0.1;
        System.out.prinln("VIPCustomer() 생성자 호출"); // 하위 클래스 생성할 때 출력
    }
    
    public int getAgentID(){
    	return agentID;
    }
}

 

CustomerTest2 클래스를 실행하여 결과를 확인해보자

public class CustomerTest2 {

	public static void main(String[] args) {
	
		VIPCustomer customerChoi = new VIPCustomer();
		customerChoi.setCustomerID(10101);
		customerChoi.setCustomerName("최민식");
		customerChoi.bonusPoint = 10000;		
		System.out.println(customerChoi.showCustomerInfo());
	}
}

Customer() 생성자가 먼저 호출되고 그다음에 VIPCustomer()가 호출된다.

상위 클래스를 상속받은 하위 클래스가 생성될 때는 반드시 상위 클래스의 생성자가

먼저 호출된다. 상위 클래스 생성자가 호출될 때 상위 클래스의 멤버 변수가 메모리에 생성되는 것이다.

이제 반대로 상위 클래스가 생성되는 과정을 보자

 

부모를 부르는 예약어 super

super 예약어는 하위 클래스에서 상위 클래스로 접근할 때 사용한다. 하위 클래스는 상위 클래스의

참조 값을 알고 있다. 이 참조 값을 가지고 있는 예약어가 super다. 

this가 자기 자신의 참조 값을 가지고 있는 것과 같다고 생각할 수 있다.

또 super는 상위 클래스의 생성자를 호출하는 데도 사용한다.

 

상위 클래스 생성자 호출하기

하위 클래스 생성자만 호출했는데 상위 클래스 생성자가 호출되는 이유는 

하위 클래스 생성자에서 super()를 자동으로 호출하기 때문이다.

super를 호출하면 상위 클래스의 디폴트 생성자가 호출된다.

public VIPCustomer(){ 
   	super(); // 컴파일러가 자동으로 추가하는 코드, 상위 클래스의 Customer()가 호출된다.
   	customerGrade = "VIP"; 
     	bonusRatio = 0.05;     
     	saleRatio = 0.1;
        System.out.prinln("VIPCustomer() 생성자 호출"); // 하위 클래스 생성할 때 출력
    }

 

super 예약어로 매개변수가 있는 생성자 호출하기

Customer 클래스를 생성할 때 고객 ID와 이름을 반드시 지정해야 한다고 하자.

set() 메서드로 값을 지정하는 게 아닌, 새로운 생성자를 만들어서 매개변수로 값을 전달받아야 한다.

디폴트 생성자가 아닌 매개변수가 있는 생성자를 직접 구현해야 한다.

public class Customer {
	
	...(생략)
    
	public Customer(int customerID, String customerName){
		this.customerID = customerID; // 매개변수로 값을 전달 받는다.
		this.customerName = customerName;
		customerGrade = "SILVER";
		bonusRatio = 0.01;
		System.out.println("Customer(int, String) 생성자 호출");
	}
    
    ...(생략)

이렇게 디폴트 생성자를 없애고 새로운 생성자를 작성하면 VIPCustomer 클래스에 오류가 발생한다.

묵시적으로 호출될 디폴트 생성자가 정의되지 않았기 때문에 반드시 명시적으로 

다른 생성자를 호출해야 한다는 뜻이다.

 

VIPCustomer  클래스를 생성할 때도 동일한 매개 변수를 넣고 상담원 ID 까지 지정한다.

기존 VIPCustomer 클래스의 디폴트 생성자도 지우고 새로 작성한다.

...(생략)

public VIPCustomer(int customerID, String customerName, int agentID) {		
		super(customerID,customerName); // 상위 클래스 생성자 호출
		customerGrade = "VIP"; 
		bonusRatio = 0.05;
		saleRatio = 0.1;
		this.agentID = agentID;
		System.out.println("VIPCustomer(int , String) 호출");
	}
    ...(생략)

 

실행 결과

VIP 등급인 최민 신 고객을 생성할 때는 상위 클래스 생성자를 먼저 호출한 후 하위 클래스 생성자의

코드 수행이 마무리된다.

 

 

상위 클래스로 묵시적 클래스 형 변환

기능면에서 보면 VIPCustomer는 Customer보다 기능이 더 많다. 상속받은 클래스는 상위 클래스의

기능을 모두 사용하고 추가로 더 많은 기능을 구현한다.

VIPCustomer는 VIPCustomer형이면서 동시에 Customer형이다.

VIPCustomer 클래스로 인스턴스를 생성할 때 인스턴스의 자료형을 Customer로 형 변환하여

선언할 수 있다. VIPCustomer클래스는 Customer 클래스를 상속받았기 때문이다.

Customer는 VIPCustomer 클래스의 기능을 다 가지고 있지 않기 때문에 역으로는 사용할 수 없다.

Customer vc = new VIPCustomer(); //가능
VIPCustomer ct = new Customer(); //불가능

 

이 후에는 동일 예제로 오버라이딩에 대해 알아보자

728x90
Comments