[Java] 상속, 오버라이딩
상속 (Inheritance)
- 부모가 자식에게 물려주는 행위
- 부모 클래스의 필드와 메소드를 자식 클래스에 물려주는 것
- 클래스를 재사용해서 새로운 클래스를 만들기 때문에 중복되는 코드를 줄이고 개발 시간을 단축
- 클래스의 수정을 최소화할 수 있음

- 상속하는 클래스 : 상위 클래스, parent class, super class
- 상속받는 클래스 : 하위 클래스, child class, sub class
- 상위 클래스는 하위 클래스 보다 더 일반적인 개념과 기능을 가짐
- 하위 클래스는 상위 클래스 보다 더 구체적인 개념과 기능을 가짐
- 하위 클래스가 상위 클래스의 속성과 기능을 확장 (extends)한다는 의미
# 하위 클래스가 생성 되는 과정
- 하위 클래스를 생성하면 상위 클래스가 먼저 생성 됨
- 클래스가 상속 받은 경우 하위 클래스의 생성자에서는 반드시 상위 클래스의 생성자를 호출 함
클래스 상속
- 프로그램에서는 자식이 부모를 선택한다.
- 자바는 다중 상속을 허용하지 않는다.
- 자식 클래스를 선언할 때 어떤 부모로 부터 상속받을 것인지를 결정하고, 부모클래스를 다음과 같이 extends 뒤에 기술한다.
public class 자식클래스 extends 부모클래스 {
}
부모 생성자 호출
- 모든 객체는 생성자를 호출해야만 생성된다. 부모도 예외는 아니다.
- 부모 생성자는 자식 생성자의 맨 첫 줄에 숨겨져 있는 super( ) 에 의해 호출
- super( )는 컴파일 과정에서 자동 추가되는데, 이것은 부모의 기본 생성자를 호출
- 만약 부모 클래스에 기본 생성자가 없다면 자식 생성자 선언에서 컴파일 에러가 발생
// 자식 생성자 선언
public 자식클래스(...) {
super();
...
}
# protected 접근 제어자
- 상위 클래스에 선언된 private 멤버 변수는 하위 클래스에서 접근 할 수 없음
- 외부 클래스는 접근 할 수 없지만, 하위 클래스는 접근 할 수 있도록 protected 접근 제어자를 사용
메소드 재정의(overriding)
- 상위 클래스에 정의된 메서드의 구현 내용이 하위 클래스에서 구현할 내용과 맞지 않는 경우
하위 클래스에서 동일한 이름의 메서드를 재정의 할 수 있음
- 부모 메소드의 선언부(리턴 타입, 메소드 이름, 매개변수)와 동일해야 한다.
- 접근 제한을 더 강하게 오버라이딩 할 수 없다.
- 새로운 예외를 throws 할 수 없다.

package ch03_1;
public class Hero {
String name;
int hp;
public Hero(String name, int hp) {
this.name = name;
this.hp = hp;
}
// 접근 제어 지시자 - protected
// 상속을 받는 자식 클래스들은 접근할 수 있다.
protected void attack() {
System.out.println("기본공격을 시작합니다.");
}
} // end of class
package ch03_1;
public class Warrior extends Hero {
// 부모 클래스에 사용자 정의 생성자가 있다면
// 자식 클래스에 반드시 부모 생성자를 먼저 호출해야 한다.
public Warrior(String name, int hp) {
// super <-- 부모를 의미한다.
//System.out.println("asdasd"); // <-- 부모가 태어나기 전에 일을 할 수 없다.
super(name, hp); // 부모 생성자를 먼저 호출해야 한다.
}
public void comboAttack() {
System.out.println(" 2단 공격을 합니다.");
}
// 상속에서 오버라이드
@Override // 어노테이션
protected void attack() {
// super.attack();
System.out.println(super.name + " 기본공격을 합니다.");
}
} // end of class
package ch03_1;
public class Archer extends Hero {
public Archer(String name, int hp) {
super(name, hp);
}
public void fireArrow() {
System.out.println("불화살 공격을 합니다.");
}
@Override
protected void attack() {
// super.attack();
System.out.println(super.name + " 기본공격을 합니다.");
}
} // end of class
public class Wizard extends Hero {
public Wizard(String name, int hp) {
super(name, hp);
}
public void freezing() {
System.out.println("얼음 공격을 합니다.");
}
@Override
protected void attack() {
// super.attack();
System.out.println(super.name + " 기본 공격을 합니다.");
}
} // end of class