본문 바로가기

STUDY/Java

[JAVA] 상속과 다형성

 

01 상속

1. 상속(inheritance): 클래스 간의 관계, 물려 받는 것

ex) B클래스가 A클래스를 상속받으면 B클래스는 A클래스의 멤버 변수와 메서드를 사용 가능하다

 

1) 클래스의 상속

 

① 상속 예약어 extends

- A 클래스가 가지고 있는 속성이나 기능을 추가로 확장하여 B 클래스를 구현한다는 의미

ex) class B extends A { }

 

 


예제: 고객 관리 프로그램 구현하기
Doit! 자바 프로그래밍 입문

* Customer Class: 고객 아이디, 이름, 등급, 보너스 포인트, 보너스 포인트 적립 비율

* VIPCustomer Class: 고객 아이디, 이름, 등급, 보너스 포인트, 보너스 포인트 적립 비율, 할인율

* VIP Customer는 항상 10% 할인 + 보너스 포인트 5% 적립

 

ex) Customer.java

package com.inheritance;

public class Customer {
	protected int customerID;
	protected String customerName, customerGrade;
	int bonusPoint;
	double bonusRatio;
	
	public Customer(int customerID, String customerName, int bonusPoint) {
		super();
		this.customerID = customerID;
		this.customerName = customerName;
		this.bonusPoint = bonusPoint;
		customerGrade = "SILVER"; // 기본 고객의 등급은 실버
		bonusRatio = 0.01; // 실버 등급의 보너스 포인트 비율
	}
	
	int calcPrice(int price) {
		bonusPoint = bonusPoint + (int)(price * bonusRatio); // 포인트 계산
		return price;
	}
	
	void showCustomerInfo() { // 고객 정보 출력
		System.out.println(customerName + "님의 등급은 " + customerGrade + "이며, 보너스 포인트는 " + bonusPoint + "입니다.");
	}
}
 

ex) VIPCustomer.java

package com.inheritance;

public class VIPCustomer extends Customer{
	double saleRatio;

	public VIPCustomer(int customerID, String customerName, int bonusPoint) {
		super(customerID, customerName, bonusPoint);
		customerGrade = "VIP"; // VIP 등급의 고객
		bonusRatio = 0.05; // VIP 등급의 보너스 포인트 비율
		saleRatio = 0.1; // VIP 등급의 세일 비율
	}

	@Override
	int calcPrice(int price) { // VIP 등급의 할인된 가격과 보너스 포인트 계산
		bonusPoint = bonusPoint + (int)(price * bonusRatio);
		return price - (int)(price * saleRatio);
	}

}
 

① 3행: VIPCustomer 클래스는 Customer 클래스를 상속받아 Customer 클래스에 선언되어 있는 customerID, customerName, customerGrade, bonusPoint, bonusRatio 멤버 변수와 calcPrice(), sowCustomerInfo() 메서드를 사용 가능

② Customer.java의 3행,4행: Customer 클래스에서 private으로 선언한 변수들은 외부 클래스에서 사용할 수 없음 > protected 예약어 사용

* private: 외부 클래스에서 사용 불가능

protected: 외부 클래스에서 사용할 수 없지만 하위 클래스에서는 사용 가능

 

ex) CustomerTest.java

package com.inheritance;

public class CustomerTest {

	public static void main(String[] args) {
		Customer lee = new Customer(10010, "이순신", 1000); // 고객ID, 이름, 현재포인트
		lee.showCustomerInfo();
		VIPCustomer kim = new VIPCustomer(10020, "김유신", 5000); // VIP고객ID, 이름, 현재포인트
		kim.showCustomerInfo();
		
		int price = 10000; // 10000원을 구매할 때 기본 고객과 VIP고객의 가격 차이
		System.out.println(lee.customerName + "님이 지불하실 금액은 " + lee.calcPrice(price) + "원 이고 현재 보너스 포인트는 " + lee.bonusPoint + "입니다.");
		System.out.println(kim.customerName + "님이 지불하실 금액은 " + kim.calcPrice(price) + "원 이고 현재 보너스 포인트는 " + kim.bonusPoint + "입니다.");
	}	
}
 

[결과화면]

 

 

위 코드들을 그림으로 표현하자면 아래와 같다.

 


 

③ 예약어 super

- 하위 클래스가 생성될 때는 상위 클래스의 생성자가 먼저 호출된다

- 하위 클래스에서 상위 클래스로 접근할 때 super 예약어를 사용한다

- 하위 클래스는 상위 클래스의 주소(참조 값)을 알고 있고 이 참조 값을 가지고 있는 예약어가 super

- 상위 클래스에 생성자 코드가 따로 없으면 super 예약어로 상위 클래스의 디폴트 생성자가 자동으로 호출된다

- 상위 클래스에 디폴트 생성자가 없고 매개변수가 있는 생성자만 있을 경우 super 예약어에 매개변수를 추가하여, 매개변수가 있는 상위 클래스의 생성자를 직접 호출해야 한다

- 현재 클래스 지정: this() / 부모 클래스 지정: super()

[결과화면]


 

2. 오버라이딩 (Overriding)

- 상위 클래스에 정의한 메서드가 하위 클래스에서 구현할 내용과 맞지 않을 경우, 하위 클래스에서 메서드를 재정의하는 것

- 오버라이딩을 하려면 반환형, 메서드 이름, 매개변수 개수, 매개변수 자료형이 반드시 같아야 한다

오버라이딩 방법 ①

ex) calcPrice.java

public int calcPrice(int price) {
		bonusPoint += price * bonusRatio;
		return price;
	}
 

ex) VIPCustomer.java

package inheritance;

public class VIPCustomer extends Customer {
	private int agentID;
	double saleRatio;
	
	@Override
	public int calcPrice(int price) {
		bonusPoint += price * bonusRatio;
		return price - (int)(price * saleRatio);
	}
 

① 7행: 하위 클래스 (VIPCustomer)의 calcPrice() 메서드 재정의

상위 클래스의 메서드와 매개변수의 자료형, 개수, 반환형을 같게 설정


 

오버라이딩 방법 ②

(1) 코드에서 오른쪽 마우스 클릭

(2) [Source] > [Override/Implement Methods...]

(3) 재정의할 메서드 선택

package inheritance;

public class VIPCustomer extends Customer {
	private int agentID;
	double saleRatio;
	
	@Override // 애노테이션(annotation): "이 메서드는 재정의된 메서드입니다"라고 컴파일러에 명확히 알려주는 역할
	public int calcPrice(int price) {
		// TODO Auto-generated method stub
		return super.calcPrice(price);
	}
 

 


 

02 다형성

1. 다형성(polymorphism)

- 하나의 코드가 여러 자로형으로 구현되어 실행되는 것 = 같은 코드에서 여러 실행 결과가 나오는 것

ex) 다형성 예제

package polymorphism;

class Animal {
	public void move() {
		System.out.println("동물이 움직입니다.");
	}
}

class Human extends Animal{
	public void move() {
		System.out.println("사람이 두 발로 걷습니다.");
	}
}

class Tiger extends Animal{
	public void move() {
		System.out.println("호랑이가 네 발로 뜁니다.");
	}
}

class Eagle extends Animal{
	public void move() {
		System.out.println("독수리가 하늘을 납니다.");
	}
}

public class AnimalTest1{
	public static void main(String[] args) {
		AnimalTest1 aTest = new AnimalTest1();
		aTest.moveAnimal(new Human());
		aTest.moveAnimal(new Tiger());
		aTest.moveAnimal(new Eagle());
	}
	
	public void moveAnimal(Animal animal) {
		animal.move();   // 재정의된 메서드가 호출됨
	}
}
 

① 어떤 인스턴스가 매개변수로 넘어와도 모두 Animal 형으로 반환

② 36행: Animal에서 상속받은 클래스가 매개변수로 넘어오면 모두 Animal형으로 반환되므로 animal.move() 메서드를 호출 가능

* animal.move() 메서드는 Animal의 move가 아닌 매개변수로 넘어온 실제 인스턴스의 메서드

* animal.move() 코드는 변함이 없지만 어떤 매개변수가 넘어왔느냐에 따라 출력문이 달라짐

 

[결과 화면]

 

2. 다형성의 장점

① 확장성: 상위 클래스를 상속받아 하위 클래스를 구성하면 모든 클래스를 상위 클래스 자료형 하나로 쉽게 관리 가능

② 유지보수가 편리: 상위 클래스에서 공통 부분의 메서드를 제공하고, 하위 클래스에서는 그에 기반한 추가 요소를 덧붙여 구현하면 코드 양도 줄어들고 유지보수도 편리