본문 바로가기

Language/Java

[Java] 상속이란?

객체 지향 프로그래밍의 중요한 특징 중 하나가 상속(inheritance)이다.

B 클래스가 A 클래스를 상속받으면 B 클래스는 A 클래스의 멤버 변수와 메서드를 사용할 수 있다.

객체 지향 프로그램은 유지보수가 편하고 프로그램을 수정하거나 새로운 내용을 추가하는 것이 유연한데, 그 기반이 되는 기술이 바로 상속이다.

 

 

자바 문법으로 상속을 구현할 때는 extends 예약어를 사용한다.

A가 가지고 있는 속성이나 기능을 추가로 확장하여 B 클래스를 구현한다는 뜻으로 사용하는 것이다.

class B extends A {

}

 

 

상속을 사용하여 고객 관리 프로그램 구현하기

 

👉[실습] Customer 클래스 구현하기
package inheritance;

public class Customer {
// 멤버 변수
	private int customerID;  // 고객 아이디
	private String customerName;  // 고객 이름
	private String customerGrade;  // 고객 등급
	int bonusPoint;  // 보너스 포인트
	double bonusRatio;  // 적립 비율
	
// 디폴트 생성자
	public Customer() {
		customerGrade = "SILVER";  // 기본 등급
		bonusRatio = 0.01;  //보너스 포인트 기본 적립 비율
	}
	
// 보너스 포인트 적립, 지불 가격 계산 메서드
	public int calcPrice(int price) {
		bonusPoint += price * bonusRatio;  // 보너스 포인트 계산
		return price;
	}
	
// 고객 정보를 반환하는 메서드
	public String showCustomerInfo() {
		return customerName + " 님의 등급은 " + customerGrade + "이며, 보너스 포인트는 "
			   + bonusPoint + "입니다.";
	}
}

 

여기에서 새로운 고객 등급이 필요한 경우

예제 시나리오

고객이 점점 늘어나고 판매도 많아지다 보니 단골 고객이 생겼다. 단골 고객은 회사 매출에 많은 기여를 하는 우수 고객이다. 이 우수 고객에게 좋은 혜택을 주고 싶다. 우수 고객 등급은 VIP이고, 다음과 같은 혜택을 제공한다.

  - 제품을 살 때는 항상 10% 할인해 준다.
  - 보너스 포인트를 5% 적립해 준다.
  - 담당 전문 상담원을 배정해 준다.

 

이 요구사항을 어떻게 구현하면 좋을까?

간단하게는 Customer 클래스에 VIP 고객에게 필요한 변수와 메서드까지 함께 포함하여 구현하는 것이지만, 이렇게 구현하면 Customer 클래스의 코드가 복잡해진다. 게다가 일반 고객은 VIP 고객 기능은 필요 없기 때문에 이런 경우 VIPCustomer 클래스를 따로 만드는 것이 좋다.

 

public class VIPCustomer {
// Customer 클래스와 겹치는 멤버 변수
	private int customerID;
	private String customerName;
	private String customerGrade;
	int bonusPoint;
	double bonusRatio;
	
// VIP 고객 관련 기능을 구현할 때만 필요한 멤버 변수
	private int agentID;  // VIP 고객 담당 상담원 아이디
	double saleRatio;     // 할인률
	
// 디폴트 생성자
	public VIPCustomer() {
		customerGrade = "VIP";  // 고객 등급 VIP
		bonusRatio = 0.05;      // 보너스 적립 5%
		saleRatio = 0.1;        // 할인률 10%
	}
	
	public int calcPrice(int price) {
		bonusPoint += price * bonusRatio;
		return price - (int)(price * saleRatio);  // 할인율 적용
	}
	
// VIP 고객에게만 필요한 메서드
	public int getAgentID() {
		return agentID; 
	}
	
	public String showCustomerInfo() {
		return customerName + " 님의 등급은 " + customerGrade + " 이며, 보너스 포인트는 "
				+ bonusPoint + "입니다.";
	}

 

위처럼 클래스를 만들고 보니 앞에서 만든 Customer 클래스와 겹치는 멤버변수와 메서드가 보이는데 이렇게 일반 고객의 속성과 기능을 다 나열할 필요 없이 Customer 클래스에 이미 구현이 다 되어 있기 때문에 VIPCustomer 클래스는 Customer 클래스를 상속받고 VIP 고객에게 필요한 추가 속성과 기능만 구현하면 된다.

 

[실습] VIPCustomer 클래스 구현하기
package inheritance;

public class VIPCustomer extends Customer {
	private int agentID;  // VIP 고객 상담원 아이디
	double saleRatio;     // 할인율
	
	public VIPCustomer() {
		customerGrade = "VIP";  // 상위 클래스에서 private 변수이므로 오류 발생
		bonusRatio = 0.05;
		saleRatio = 0.1;
	}
	
	public int getAgentID() {
		return agentID;
	}
}

 

이렇게 VIPCustomer 클래스의 코드가 상당히 간단해졌다.

여기에서는 customerGrade변수가 상위클래스에서 private 변수로 선언되었기 때문에 외부 클래스에서는 접근할 수 없어 오류가 발생한다.

 

 

상위 클래스 변수를 사용하기 위한 protected 예약어

 

customerGrade에서 발생하는 오류는 protected 예약어를 사용하면 된다.

protected 예약어는 상위클래스에 작성한 변수나 메서드 중 외부 클래스에서 사용할 수 없지만 하위 클래스에서는 사용할 수 있도록 지정하는 것이다. 즉, 상속받은 하위 클래스에서는 public처럼 사용할 수 있는 것이다.

 

[실습] protected 변수 선언
package inheritance;

public class Customer {
// 멤버 변수
	protected int customerID;  // 고객 아이디
	protected String customerName;  // 고객 이름
	protected String customerGrade;  // 고객 등급
	int bonusPoint;  // 보너스 포인트
	double bonusRatio;  // 적립 비율
	
...
	
// protected 예약어로 선언한 변수를 외부에서 사용할 수 있도록 get(), set() 메서드 추가
	public int getCustomerID() {
		return customerID;
	}
	
	public void setCustomerID(int customerID) {
		this.customerID = customerID;
	}
	
	public String getCustomerName() {
		return customerName;
	}
	
	public void setCustomerName(String customerName) {
		this.customerName = customerName;
	}
	
	public String getCustomerGrade() {
		return customerGrade;
	}
	
	public void setCustomerGrade(String customerGrade) {
		this.customerGrade = customerGrade;
	}
}

 

Customer 클래스를 상속받은 VIPCustomer 클래스는 protected로 선언한 변수를 상속받게 되고, 나머지 public 메서드도 상속받아 사용할 수 있다. 위와 같이 protected로 선언하면 VIPCustomer 부분의 오류는 사라진다.

 

 

테스트 프로그램 실행하기

예제 시나리오

일반 고객 1명과 VIP 고객 1명이 있다. 일반 고객의 이름은 이순신, 아이디는 10010이다. 이 고객은 지금 보너스 포인트 1000점이 있다. VIP고객의 이름은 김유신, 아이디는 10020이다. 이 고객은 보너스 포인트 10000점을 가지고 있다.
[실습] 상속 클래스 테스트하기
package inheritance;

public class CustomerTest1 {
	public static void main(String[] args) {
		Customer customerLee = new Customer();
		customerLee.setCustomerID(10010);    // protected 변수로 set() 메서드 호출
		customerLee.setCustomerName("이순신"); // protected 변수로 set() 메서드 호출
		customerLee.bonusPoint = 1000;
		System.out.println(customerLee.showCustomerInfo());
		
		VIPCustomer customerKim = new VIPCustomer();
		customerKim.setCustomerID(10020);
		customerKim.setCustomerName("김유신");
		customerKim.bonusPoint = 10000;
		System.out.println(customerKim.showCustomerInfo());
	}
}

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

[Java] 메서드 오버라이딩  (1) 2022.12.13
[Java] 상속에서 클래스 생성과 형 변환  (0) 2022.11.20
[Java] ArrayList 클래스 사용하기  (0) 2022.11.15
[Java] 다차원 배열  (0) 2022.11.12
[Java] 배열이란?  (0) 2022.11.07