먼저 아래와 같이 Customer 라는 고객 정보를 담는 클래스가 있다.
public class Customer {
private int customerID; // 고객아이디
private String customerName; // 고객 이름
private String customerGrade; // 고객 등급
int bonusPoint; // 포인트 합계
double bonusRatio; // 포인트 적립률
public Customer() {
customerGrade = "SILVER"; // 고객 등급을 SILVER로 지정
bonusRatio = 0.01; // 포인트 적립률을 1%로 지정
}
public int calcPrice(int price) { // 보너스 포인트 계산 메서드
bonusPoint += price * bonusRatio;
return price;
}
public String getCustomerInfo() { // 고객 정보를 반환하는 메서드
return customerName + " 님의 등급은 " + customerGrade + "이며, 보너스 포인트는 " + bonusRatio + "입니다.";
}
}
위와 같은 코드에서 모든 멤버 변수가 반드시 private으로 선언할 필요는 없다. 필요에 따라 멤버 변수나 메서드를 외부에 노출하지 않을 목적일 때 private으로 선언할 수 있다.
여기서 다음 경우를 생각해보자.
위와 같은 코드를 적용해서 운영하고 있는 매장이 있을 때 고객이 점점 늘어나고 판매도 많아지게 되니 단골 고객이 생기게 되었을 경우, 이 고객에게 혜택을 주고싶어서 고객의 등급을 VIP로 지정하고, 제품을 살 때 항상 10% 할인을 해주고, 보너스 포인트 적립 비율을 1%->5%로 변경하고, 아이디를 가진 전문 상담원을 배정해주고 싶을 때는...?
가장 간단한 경우는 이미 Customer 클래스가 존재하기 때문에 Customer 클래스에 VIP 고객에게 필요한 변수와 메서드까지 함께 포함하여 구현하는 것이다. 하지만 이렇게 구현하게 되면 Customer 클래스의 코드가 복잡해지고, 일반 고객의 인스턴스를 생성할 때 VIP 고객의 기능은 필요없는데 VIP 고객의 내용까지 같이 생성되기 때문에 낭비가 발생한다.
그렇기 때문에 아래와 같이 VIPCustomer 클래스를 따로 생성해주는 것이 좋다.
public class VIPCustomer {
private int customerID;
private String customerName;
private String customerGrade;
int bonusPoint;
double bonusRatio;
private int agentID;
double saleRatio;
public VIPCustomer() {
customerGrade = "VIP";
bonusRatio = 0.05;
saleRatio = 0.1;
}
public int calcPrice(int price) {
bonusPoint += price * bonusRatio;
return price - (int)(price * saleRatio);
}
public int getAgentID() {
return agentID;
}
public void showCustomerInfo() {
return customerName + " 님의 등급은 " + customerGrade + "이며, 보너스 포인트는" + bonusPoint + "입니다.";
}
}
하지만 위와 같이 클래스를 생성하게 되면 앞서 생성한 Customer 클래스와 겹치는 멤버 변수와 메서드가 존재한다. 또 calcPrice( ) 메서드는 이름은 같은데 구현 내용이 다르다. 바로 이런 경우에 상속을 사용하여 클래스를 구현한다.
즉 Customer 클래스에 일반 고객의 속성과 기능이 이미 구현되어 있기 때문에, VIPCustomer 클래스는 Customer 클래스를 상속받고 VIP 고객에게 필요한 추가 속성과 기능을 구현하는 것이다. Customer 클래스를 상속하여 VIPCustomer 클래스를 구현한 결과는 다음과 같다.
public class VIPCustomer extends Customer {
private int agentID;
double saleRatio;
public VIPCustomer() {
customerGrade = "VIP";
bonusRatio = 0.05;
saleRatio = 0.01;
}
public int agentID() {
return agentID;
}
}
이전 코드들과 비교했을 때, VIPCustomer 클래스의 코드가 간단해졌다.
하지만 위 코드는 오류가 발생한다.
customerGrade 변수에서 오류가 발생하는데, 원인은 상위 클래스인 Customer 클래스에서 customerGrade를 private 변수로 선언하였기 때문에 외부 클래스에서는 이 변수를 사용할 수 없다는 오류이다.
이를 해결하기 위해 protected 예약어를 사용한다.
protected 예약어는 상위클래스에서 작성한 변수나 메서드 중 외부 클래스에서 사용할 수 없지만 상속받은 하위 클래스에서는 public처럼 사용할 수 있도록 지정하는 예약어이다. 즉, protected는 상속된 하위 클래스를 제외한 나머지 외부 클래스에서는 private과 동일한 역할을 한다.
자 그럼 Customer 클래스에 있는 private 변수를 다른 하위 클래스에서도 사용할 수 있도록 모두 protected로 변경해보자.
public class Customer {
protected int customerID; // protected로 변경
protected String customerName; // protected로 변경
protected String customerGrade; // protected로 변경
...
...
}
그리고 protected로 선언한 customerID, customerName, customerGrade 변수를 사용하기 위해 get( ), set( ) 메서드를 추가하자.
// protected 예약어로 선언한 변수를 외부에서 사용할 수 있도록 get( ), set( ) 메서드를 추가
public class Customer {
protected int customerID;
protected String customerName;
protected String customerGrade;
int bonusPoint;
double bonusRatio;
...
public int getCustomerID( ) {
return customerID;
}
public void setCustomerID(int customerID) {
this.customerID = customerID;
}
public String getCustomerName( ) {
return customerName;
}
public void getCustomerName(String customerName) {
this.customerName = customerName;
}
public String getCustomerGrade( ) {
return customerGrade;
}
public void getCustomerGrade(String customerGrade) {
this.customerGrade = customerGrade;
}
예제로 아래와 같은 시나리오의 CustomerTest.java 파일을 구현해보자.
예제 시나리오
일반 고객 1명과 VIP 고객 1명이 있다.
일반 고객의 이름은 이순신, 아이디는 10010이고, 보너스 포인트 1000점이 있다.
VIP 고객의 이름은 김유신, 아이디는 10020이고, 보너스 포인트 10000점이 있다.
public class customerTest {
public static void main(String[] args) {
Customer customerLee = new Customer();
customerLee.setCustomerName("이순신");
customerLee.setCustomerID(10010);
customerLee.bonusPoint = 1000;
System.out.println(customerLee.getCustomerInfo());
Customer customerKim = new VIPCustomer();
customerKim.setCustomerName("김유신");
customerKim.setCustomerID(10020);
customerKim.bonusPoint = 10000;
System.out.println(customerKim.getCustomerInfo());
}
}
'웹 개발 기초 > 자바 문법' 카테고리의 다른 글
다형성 활용, 상속을 사용하는 경우, IS-A 관계, HAS-A 관계 (0) | 2022.12.07 |
---|---|
가상메서드 (1) | 2022.12.06 |
메서드 오버라이딩, 메서드 오버로딩, 가상 메서드의 원리 (0) | 2022.12.05 |
상속에서의 클래스 생성 (0) | 2022.12.05 |
배열, ArrayList 클래스 (0) | 2022.12.02 |