본문 바로가기

Language/Java

[Java] 상속에서 클래스 생성과 형 변환

하위 클래스가 생성될 때는 상위 클래스의 생성자가 먼저 호출된다.

 

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

상속된 하위 클래스가 생성되는 과정을 다시 살펴보기 위해 Customer와 VIPCustomer 클래스에 생성자 출력문 추가하여 출력 결과를 확인해본다.

 

[실습] 상속에서 클래스 생성 과정 (1)
package inheritance;

public class Customer {
// 멤버 변수
	protected int customerID;  // 고객 아이디
	protected String customerName;  // 고객 이름
	protected String customerGrade;  // 고객 등급
	int bonusPoint;  // 보너스 포인트
	double bonusRatio;  // 적립 비율
	
// 디폴트 생성자
	public Customer() {
		customerGrade = "SILVER";  // 기본 등급
		bonusRatio = 0.01;  //보너스 포인트 기본 적립 비율
		System.out.println("Customer() 생성자 호출");  //상위 클래스 생성할 때 콘솔 출력문
	}
	
// 보너스 포인트 적립, 지불 가격 계산 메서드
	public int calcPrice(int price) {
		bonusPoint += price * bonusRatio;  // 보너스 포인트 계산
		return price;
	}
	...
}

 

[실습] 상속에서 클래스 생성 과정 (2)
package inheritance;

public class VIPCustomer extends Customer {
	private int agentID;  // VIP 고객 상담원 아이디
	double saleRatio;     // 할인율
	
	public VIPCustomer() {
		customerGrade = "VIP";  // 상위 클래스에서 private 변수이므로 오류 발생
		bonusRatio = 0.05;
		saleRatio = 0.1;
		System.out.println("VIPCustomer() 생성자 호출");  // 하위 클래스 생성할 때 콘솔 출력문
	}
	
	public int getAgentID() {
		return agentID;
	}
}

 

[실습] 하위 클래스 생성하기
package inheritance;

public class CustomerTest2 {
	public static void main(String[] args) {
		VIPCustomer customerKim = new VIPCustomer();  // 하위 클래스 생성
		customerKim.setCustomerID(10020);
		customerKim.setCustomerName("김유신");
		customerKim.bonusPoint = 10000;
		System.out.println(customerKim.showCustomerInfo());
	}
}

 

출력 화면을 보면 상위 클래스의 Customer() 생성자가 먼저 호출되고 그다음에 VIPCustomer()가 호출되는 것을 알 수 있다.

즉, 상위 클래스를 상속받은 하위 클래스가 생성될 때는 반드시 상위 클래스의 생성자가 먼저 호출된다.

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

 

위처럼 상위 클래스의 변수가 메모리에 먼저 생성되기 때문에 하위 클래스에서도 이 값을 모두 사용할 수 있다.

그렇다면 private로 선언한 경우 하위 클래스에서 해당 변수를 사용할 수 없었던 것은 private 변수가 생성되지만, 단지 하위 클래스에서 접근할 수 없었기 때문이다.

 

 

부모를 부르는 예약어, super

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

하위 클래스는 상위 클래스의 주소, 즉 참조 값을 알고 있는데, 이 값을 가지고 있는 예약어가 바로 super이다.

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

하위 클래스 생성자만 호출했을 때 상위 클래스 생성자가 호출되는 이유는 하위 클래스 생성자에서 super()를 자동으로 호출하기 때문이다.

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

 

[실습] Customer 클래스에 새로운 생성자 추가하기
...

// 디폴트 생성자
	public Customer(int customerID, String customerName) {
		this.customerID = customerID;
		this.customerName = customerName;
		customerGrade = "SILVER";  // 기본 등급
		bonusRatio = 0.01;  //보너스 포인트 기본 적립 비율
		System.out.println("Customer(int, String) 생성자 호출");  //상위 클래스 생성할 때 콘솔 출력문
	}

...

 

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

이 오류는 묵시적으로 호출될 디폴트 생성자 Customer()가 정의되지 않았기 때문에 반드시 명시적으로 다른 생성자를 호출해야 한다는 뜻이다.

 

[실습] 명시적으로 상위 클래스 생성자 호출하기
...

public VIPCustomer(int customerID, String CustomerName, int agentID) {
		super(customerID, customerName);
		customerGrade = "VIP";  // 상위 클래스에서 private 변수이므로 오류 발생
		bonusRatio = 0.05;
		saleRatio = 0.1;
		this.agentID = agentID;
		System.out.println("VIPCustomer(int, String, int) 생성자 호출");  // 하위 클래스 생성할 때 콘솔 출력문
	}

...

 

이대로 테스트해보면

package inheritance;

public class CustomerTest2 {
	public static void main(String[] args) {
		VIPCustomer customerKim = new VIPCustomer(10020, "김유신", 1111);  // 하위 클래스 생성
//		customerKim.setCustomerID(10020);
//		customerKim.setCustomerName("김유신");
		customerKim.bonusPoint = 10000;
		System.out.println(customerKim.showCustomerInfo());
	}
}

위처럼 set() 메서드는 주석처리하고 실행해보면

 

이상 없이 출력되는 것을 확인할 수 있다.

 

상위 클래스에서 선언한 멤버 변수나 메서드를 하위 클래스에서 참조할 때도 super를 사용한다.

VIPCustomer의 showVIPInfo() 메서드에서 상위 클래스의 showCustomerInfo() 메서드를 참조해 담당 상담원 아이디를 추가로 출력하려고 할 때 아래와 같이 구현이 가능하다.

public String showVIPInfo() {
	return super.showCustomerInfo() + "담당 상담원 아이디는 " + agentID + "입니다.";
}

 

 

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

Customer 클래스보다 VIPCustomer 클래스가 상위 클래스 기능과 더불어 더 많은 기능을 구현하기 때문에 기능이 더 많다.

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

즉, VIPCustomer 클래스로 인스턴스를 생성할 때 이 인스턴스의 자료형을 Customer형으로 클래스 형 변환하여 선언이 가능한데, 이는 VIPCustomer 클래스가 Customer 클래스를 상속받았기 때문이다.

Customer vc = new VIPCustomer();

'Language > Java' 카테고리의 다른 글

[Java] 다형성(polymorphism)  (0) 2022.12.15
[Java] 메서드 오버라이딩  (1) 2022.12.13
[Java] 상속이란?  (0) 2022.11.17
[Java] ArrayList 클래스 사용하기  (0) 2022.11.15
[Java] 다차원 배열  (0) 2022.11.12