본문 바로가기
객체 지향 프로그래밍/Java

chapter 8. 상속과 다형성 (수정중)

by xangmin 2022. 3. 18.
반응형

8-1. 상속이란?

클래스의 상속

객체지향 프로그래밍의 중요한 특징 중 하나가 상속(inheritance)이다. 상속은 일반적으로 알 듯 무언가를 물려받는다는 의미이다. B 클래스가 A 클래스를 상속받으면 B 클래스는 A 클래스의 멤버 변수와 메서드를 사용할 수 있다.

 

클래스 상속 문법

자바 문법으로 상속을 구현할 때는 extends 예약어를 사용한다. 이때 사용하는 extends 예약어는 '연장, 확장하다'의 의미이다. 즉 A가 가지고 있는 속성이나 기능을 추가로 확장하여 B클래스를 구현한다는 뜻이다. 즉 A가 가지고 있는 속성이나 기능을 추가로 확장하여 B 클래스를 구현한다. 

class B extends A {	//'B 클래스가 A 클래스를 상속받는다'
}

 

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

package ingeritance;

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% 적립해 줍니다.

· 담당 전문 상담원을 배정해 줍니다.

 

이 요구 사항을 위한 VIPCostomer 클래스를 구현해보자.

Customer 클래스에 일반 고객의 속성과 기능이 이미 구현되어 있기 때문에, VIPCustomer 클래스는 Customer 클래스를 상속받고 VIP 고객에게 필요한 추가 속성과 기능을 구현하는 것이다. Customer 클래스를 상속한 VIPCustomer 클래스의 코드는 다음과 같다.

package ingeritance;

public class VIPCustomer extends Customer {
	private int agentID;
	double saleRatio;
	
	public VIPCustomer() {
		customerGrade = "VIP";	// 상위 클래스에서 private 변수이므로 오류 발생
		bonusRatio = 0.05;
		saleRatio = 0.1;
	}

	public int getAgentID() {
		return agentID;
	}
}

 

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

우선 customerGrade 변수에서 발생하는 오류부터 수정하자. customerGrade가 private 변수이기 때문에 오류가 발생한다. protected 예약어로 선언한 변수는 외부 클래스에는 private 변수처럼 get() 메서드를 사용해 값을 가져올 수 있고, set() 메서드를 사용해 값을 지정할 수 있다. Customer 클래스를 상속받은 VIPCustomer 클래스는 protected로 선언한 변수를 상속받게 되고, 나머지 public 메서드도 상속받아 사용할 수 있다.

package ingeritance;

public class Customer {
	protected int customerID;		//멤버 변수
	protected String customerName;
	protected 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 + "입니다.";
	}
	
	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 setCusomerGrade(String customeGrade) {
		this.customerGrade = customerGrade;
	}
}

 

테스트 프로그램 실행하기

예제 시나리오

일반 고객 1명과 VIP 고객 1명이 있습니다. 일반 고객의 이름은 이순신, 아이디는 10010입니다. 이 고객은 지금 보너스 포인트 1000점이 있습니다. VIP 고객의 이름은 김유신, 아이디는 10020입니다. 이 고객은 보너스 포인터를 10000점을 가지고 있습니다.

 

package ingeritance;

public class CustomerTest1 {
	public static void main(String[] args) {
		Customer customerLee = new Customer();
		customerLee.setCustomerID(10100);
		customerLee.setCustomerName("이순신");
		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());
	}
}

 

8-2. 상속에서 클래스 생성과 형 변환

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

상속을 받은 하위 클래스는 상위 클래스의 변수와 메서드를 사용할 수 있다록 했다. 즉, CustomerTest 예제를 살펴보면, VIPCoustomer 클래스로 선언한 customerKim 인스턴스는 상속받은 상위 클래스의 변수를 자기 것처럼 사용할 수 있다.

package ingeritance;

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() 생성자 호출");	//상위 클래스 생성할 때 콘솔 출력문
	}
    
    ...
}
package ingeritance;

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

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() 생성자 호출
김유신님의 등급은 VIP이며, 보너스 포인트는 10000입니다.

출력화면을 보면 상위 클래스의 Customer() 생성자가 먼저 호출되고 그 다음에 VIPCustomer()가 호출되는 것을 알 수 있다. 정리하면 상위 클래스를 상속받은 하위 클래스가 생성될 때는 반드시 상위 클래스의 생성자가 먼저 호출된다. 그리고 상위 클래스 생성자가 호출될 때 상위 클래스의 멤버 변수 메모리에 생성되는 것이다.

 

반응형

'객체 지향 프로그래밍 > Java' 카테고리의 다른 글

chapter 7. 배열과 ArrayList  (0) 2022.03.15
chapter 6. 클래스와 객체2  (0) 2022.03.12
chapter 9. 추상 클래스  (0) 2022.03.11
chapter 5. 클래스와 객체1  (0) 2022.03.10
chapter 4. 제어 흐름 이해하기  (0) 2022.02.23

댓글