Java

[Java] 상속

k_sangmin 2023. 8. 22. 17:37

클래스 상속

  • 새로운 클래스를 정의할 때 이미 구현된 클래스를 상속받아서 속성이나 기능을 확장하여 클래스를 구현함
  • 이미 구현된 클래스보다 더 구체적인 기능을 가진 클래스를 구현해야 할 때 기존 클래스를 상속함

상속을 구현하는 경우

  • 상위 클래스는 하위 클래스 보다 더 일반적인 개녕과 기능을 가짐
  • 하위 클래스는 상위 클래스 보다 더 구체적인 개녕과 기능을 가짐
  • 하위 클래스가 상위 클래스의 속성과 기능을 (extends) 한다는 의미

용어정리

  • 상속하는 클래스 : 상위 클래스, parent class, super class
  • 상속받는 클래스 : 하위 클래스, child class, subclass

상속 활용 예제

일반 고객 클래스 구현

  • 고객의 속성 : 고객 아이디, 고객 이름, 고객 등급 보너스 포인트, 포인트 적립비율
  • 일반 고객의 경우 물품 구매시 1%의 보너스 포인트 적립
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 + "입니다.";			
	}
}

골드 고객 클래스 구현

  • 매출에 더 많은 기여를 하는 단골 고객
  • 보너스 포인트는 제품 가격의 5%를 적립해 줌
  • 담당 전문 상담원이 배정됨
  • Customer에 구현된 내용과 중복되는 부분은 Customer를 상속하여 구현
public class GoldCustomer extends Customer {
	private int agentID;
	double salesRatio;

	public GoldCustomer() {
		customerGrade = "GOLD";
		bonusRatio = 0.05;
		salesRatio = 0.1;
	}
	public int getAgentId() {
		return agentID;
	}
}

접근 제어 지시자

  • 상위 클래스에 선언된  private 멤버 변수는 하위 클래스에서 접근할 수 없음
  • 외부 클래스는 접근 할 수 없지만, 하위 클래스는 접근할 수 있도록 protected 접근 제어 지시자 사용
	protected int customerId;
	protected String customerName;
	protected String customerGrade;

get()/set() 구현

  • 접근 제어 지시자로 인해 접근할 수 없는 멤버변수에 접근하기위해 getter setter를 이용해 접근
	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;
	}

클래스 사용

  • GoldCustomer 클래스로 생성한 인스턴스도 Customer 클래스에 생성된 매개변수나 메서드를 사용할 수 있다.
public class MainTest {
	public static void main(String[] args) {
		Customer customer_Lee = new Customer();
		customer_Lee.setCustomerName("이성계");
		customer_Lee.setCustomerId(10010);
		customer_Lee.bonusPoint = 1000;
		System.out.println(customer_Lee.showCustomerInfo());
		
		GoldCustomer customer_jung = new GoldCustomer();
		customer_jung.setCustomerName("정몽주");
		customer_jung.setCustomerId(10020);
		customer_jung.bonusPoint = 10000;
		System.out.println(customer_jung.showCustomerInfo());
	}
}

상속에서 클래스 생성 과정과 형변환

하위클래스 생성 과정

  • 하위 클래스를 생성하면 상위 클래스가 먼저 생성
  •  new GoldCustomer()클래스를 호출하면 그 부모 클래스인 Customer() 생성자가 먼저 호출
  • 클래스가 상속 받은 경우 하위 클래스의 생성자에서는 반드시 상위 클래스 생성자를 호출
public Customer() {
		customerGrade = "SILVER";
		bonusRatio = 0.01;
		System.out.println("Customer클래스 생성자 호출");
	}
public GoldCustomer() {
		customerGrade = "GOLD";
		bonusRatio = 0.05;
		salesRatio = 0.1;
		System.out.println("GOLD Customer클래스 생성자 호출");

	}
  • new GoldCustomer()클래스를 호출 시
  • Customer 클래스 생성자가 먼저 호출되는 것을 확인할 수 있음

Customer클래스 생성자 호출

GOLD Customer클래스 생성자 호출

Super 키워드

  • 하위 클래스에서 가지는 상위 클래스에 대한 참조 값
  • super()는 상위 클래스의 기본 생성자를 호출 함
  • 하위 클래스에서 명시적으로 상위 클래스의 생성자를 호출하지 않으면 super()가 호출됨                                                (이때 반드시 상위 클래스의 기본 생성자가 존재 해야함)
  • 상위 클래스의 기본생성자가 없는 경우 (다른 생성자가 있는 경우) 하위 클래스에서는 생성자에서 super를 이용하여 명시적으로 상위클래스의 생성자를 호출 함
  • super는 생성된 상위 클래스 인스턴스의 참조 값을 가지므로 super를 이용하여 상위 클래스의 메서드나 멤버변수에 접근할 수 있음
//부모 클래스의 생성자에 디폴트 생성자를 없애고 매개변수가 있는 생성자 추가
public Customer(int customerID, String customerName) {
		this.customerId = customerID;
		this.customerName = customerName;
		
		customerGrade = "SILVER";
		bonusRatio = 0.01;
		System.out.println("Customer클래스 생성자 호출");
	}
//자식 클래스의 생성자도 부모클래스의 생성자와 같은 형태를 유지해야함
//super 키워드를 이용하여 명시적으로 호출
public GoldCustomer(int customerID, String CustomerName) {
		super(customerID,CustomerName);
		
		customerGrade = "GOLD";
		bonusRatio = 0.05;
		salesRatio = 0.1;
		System.out.println("GOLD Customer클래스 생성자 호출");

	}

형 변환 (업 캐스팅)

  • 상위 클래스로 변수를 선언하고 하위 클래스의 생성자로 인스턴스를 생성
Customer Customer_1 = new GoldCustomer(10030,"고객1");
  • 상위 클래스 타입의 변수에 하위 클래스 변수 대입
  • 하위 클래스는 상위 클래스의 타입을 내포하고 있으므로 상위 클래스로의 묵시적 형 변환이 가능함
  • 상속 관계에서 모든 하위 클래스는 상위 클래스로 형변환(업 캐스팅) 됨 (역은 성립하지 않음) 

형 변환과 메모리

Customer Customer_1 = new GoldCustomer(10030,"고객1");
  • GoldCustomer() 생성자에 의해 GoldCustomer 클래스의 모든 멤버 변수에 대한 메모리는 생성되었지만, 변수의 타입이 Cusomer 이므로 실제 겁근 가능한 변수나 메서드는 Customer의 변수와 메서드이다.

메서드 재정의하기(overring)

  • 오버라이딩(overriding): 상위 클래스에 정의된 메서드의 구현 내용이 하위 클래스에서 구현할 내용과 맞지 않는 경우 하위 클래스에서 동일한 이름의 메서드를 재정의 할  수 있다.
  • GoldCustomer클래스는 Customer클래스와 할인율이 다르기때문에 메서드를 재정의 해야함
@Override
public int calcPrice(int price) {
	bonusPoint +=price *bonusRatio;
	return price - (int)(price * salesRatio);
}

@overriding 어노테이션(annotation)

  • 애노테이션은 원래 주석이라는 의미
  • 컴파일러에게 특별한 정보를 제공해주는 역활
  • @overriding  애노테이션은 재정의 된 메서드라는 의미로 선언부가 기존의 메서드와 다른 경우 에러가남

형 변환과 오버라이딩 메서드 호출

Customer Customer_1 = new GoldCustomer(10030,"고객1");

Customer_1변수의 타입은 Customer지만 인스턴스의 타입은 GoldCustomer임 자바에서는 항상 인스턴스의 메서드가 호출됨