Super Coding Addict
Ch07. 상속과 다형성 (1) 본문
< 상속이란? >
* 클래스에서 '상속' 의 의미
- 객체지향 프로그램의 특징! (C++, C#, Javascript에서 사용하는 상속의 의미와 동일)
- 어떤 클래스가 있는데, 그 클래스보다 확장된 기능을 구현하겠다고 하면, 그 클래스의 기능과 속성을 상속받아 확장!
- 코드 재사용되긴 하지만, 코드 재사용의 방법이라고 이해해선 안됨
- 이질적 클래스 간에는 상속을 쓰는 게 X
- 상속하는 클래스 : parent class / 상속 받는 클래스 : child class (subclass)
--> class B extends A
- java는 상속이 1개밖에 안됨 ! (single inheritance만을 지원)
cf. c++은 다중상속 가능
* 상속을 사용하는 경우
- 상위클래스 : 일반적 개념과 기능 / 하위클래스 : 구체적 개념과 기능
* 상속을 사용하여 고객관리 프로그램 구현하기
[ Customer 클래스 -- 부모클래스 ]
package inheritance;
public class Customer {
protected int customerID; //private이면 자손클래스에서 접근불가
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 setCustomerGrade(String customerGrade) {
this.customerGrade = customerGrade;
}
}
[ VIPCustomer 클래스 -- 자식클래스 ]
package inheritance;
//Customer 클래스보다 속성과 기능이 더 확장된 클래스!
public class VIPCustomer extends Customer{
double salesRatio;
private int agentID;
public VIPCustomer() {
customerGrade = "VIP";
bonusRatio = 0.05;
salesRatio = 0.1;
}
}
* protected 예약어
- 외부 클래스에는 private으로, 하위 클래스에는 public의 기능을 구현한 키워드
- 상위 클래스에 protected로 선언된 변수나 메서드는 다른 외부 클래스에서는 사용 불가 but 하위 클래스에서는 사용 가능
* 접근 제한자(access modifier)의 가시성
외부클래스 | 하위클래스 | 동일패키지 | 내부클래스 | |
public | O | O | O | O |
protected | X | O | O | O |
default | X | X | O | O |
private | X | X | X | O |
* 테스트 시나리오 (앞의 고객 클래스들)
[ CustomerTest 클래스 -- 메인 ]
package inheritance;
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.showCustomerInfo());
VIPCustomer customerKim = new VIPCustomer();
customerKim.setCustomerName("김유신");
customerKim.setCustomerID(10020);
customerKim.bonusPoint = 10000;
System.out.println(customerKim.showCustomerInfo()); //상속받은 메서드 사용
}
}
/*
결과:
이순신님의 등급은 SILVER이며, 적립된 보너스 포인트는 1000점 입니다.
김유신님의 등급은 VIP이며, 적립된 보너스 포인트는 10000점 입니다.
*/
< 상속에서 클래스 생성 과정과 형 변환 >
* 하위 클래스가 생성되는 과정
- 하위 클래스가 생성될 때 상위 클래스가 먼저 생성된다
--> 상위 클래스 생성자 호출 -> 하위 클래스 생성자 호출
--> 하위 클래스 생성자에서 상위 클래스 생성자가 무조건 호출되어야 함
- 하위 클래스에서 상위 클래스 생성자 호출코드가 없어도, 컴파일러가 알아서 super()를 추가하여 상위 클래스 기본 생성자를 호출한다
--> 만약 상위 클래스 기본생성자가 없다면, 하위 클래스가 명시적으로 상위 클래스 생성자를 호출해야 함
- 예제
[ Customer 클래스 - 상위 클래스 ]
package inheritance;
public class Customer {
protected int customerID; //private이면 자손클래스에서 접근불가
protected String customerName;
protected String customerGrade;
int bonusPoint;
double bonusRatio;
/*
public Customer() {
//생성자에서 멤버변수 초기화를 많이 함
customerGrade = "SILVER";
bonusRatio = 0.01;
System.out.println("Customer() 생성자 호출");
}
*/
public Customer(int customerID, String customerName) {
this.customerID = customerID;
this.customerName = customerName;
customerGrade = "SILVER";
bonusRatio = 0.01;
System.out.println("Customer(int, String) 생성자 호출");
}
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 setCustomerGrade(String customerGrade) {
this.customerGrade = customerGrade;
}
}
--> 상위 클래스에서 기본생성자 대신에 매개변수가 있는 생성자가 있다면! 하위 클래스에서 어떻게 해야 할까?
[ VIPCustomer 클래스 - 하위 클래스 ]
package inheritance;
//Customer 클래스보다 속성과 기능이 더 확장된 클래스!
public class VIPCustomer extends Customer{
double salesRatio;
private int agentID;
/*
public VIPCustomer() {
//super(); //상위 클래스의 기본생성자 호출 - 따로 안넣어도 프리컴파일 단계에서 컴파일러가 넣어줌
super(0, null);
customerGrade = "VIP";
bonusRatio = 0.05;
salesRatio = 0.1;
System.out.println("VIPCustomer() 생성자 호출");
}
*/
public VIPCustomer(int customerID, String customerName) {
super(customerID, customerName);
customerGrade = "VIP";
bonusRatio = 0.05;
salesRatio = 0.1;
System.out.println("VIPCustomer(int, String) 생성자 호출");
}
}
--> 상위 클래스의 생성자가 기본생성자가 아니므로, 상위 클래스의 생성자를 직접 불러줘야 한다.
상위 클래스의 생성자가 int, String 형의 2개 매개값을 받으므로 마찬가지로 2개의 매개값을 넣어주어 상위 클래스
생성자를 호출한다.
===> 결과는,
Customer(int, String) 생성자 호출
VIPCustomer(int, String) 생성자 호출
김유신님의 등급은 VIP이며, 적립된 보너스 포인트는 10000점 입니다.
다음과 같이 상위클래스 생성자가 먼저 호출된 후 하위 클래스 생성자가 호출됨을 알 수 있다.
* 상속에서의 메모리 상태
- 상위 클래스의 인스턴스가 먼저 생성되고 --> 하위 클래스의 인스턴스가 생성된다.
* 상위 클래스로의 묵시적 형 변환 (업캐스팅)
- 상위 클래스 형으로 변수를 선언하고, 하위 클래스 인스턴스를 생성 가능
- 하위 클래스는 상위 클래스의 타입을 내포 --> 상위 클래스로 묵시적 형변환 가능
- 상속관계에서 모든 하위 클래스는 상위 클래스로 묵시적 형 변환이 됨 (역은 성립X)
( 하위 클래스에는 상위 클래스의 내용이 다 있으니까 가능!!! )
--> customerKim를 상위 클래스인 Customer 클래스 형으로 선언한 뒤 하위 클래스인 VIPCustomer 클래스로 인스턴스 생성
--> 힙메모리에는 상위클래스와 하위클래스의 멤버변수가 모두 메모리에 생성이 되었지만,
customerKim의 형이 상위 클래스인 Customer이기 때문에 Cusmoter의 멤버변수만 사용할 수 있음
'JAVA 문법' 카테고리의 다른 글
Ch12. 람다식 (2) (0) | 2021.02.06 |
---|---|
Ch12. 람다식 (1) (0) | 2021.02.06 |
Ch06. 배열(2) (0) | 2021.01.20 |
Ch06. 배열(1) (0) | 2021.01.19 |
Ch05. 클래스와 객체(3) (0) | 2021.01.19 |