[Java] 클래스의 상속
상속의 기본
기존 정의된 클래스에 메서드와 변수를 추가하여 새로운 클래스를 정의하는 것을 상속이라고 한다.
이때 기존 정의된 클래스를 부모 클래스(상위 클래스)라 하고, 부모 클래스를 상속해 새로 정의한 클래스를 자식 클래스(하위 클래스)라고 한다. 자식 클래스는 부모 클래스의 변수와 메서드를 가진다.
class Man {
String name;
public Man(String name) {
this.name = name;
}
}
class BusinessMan extends Man {
String company;
String position;
public BusinessMan(String name, String company, String position) {
super(name);
this.company = company;
this.position = position;
}
}
위 코드를 보면 Man 클래스는 부모 클래스, BusinessMan 클래스는 자식 클래스라고 할 수 있다.
추가로, 자바는 단일 상속만을 지원한다.
static 선언이 붙는 클래스 변수와 메서드도 접근수준 지시자가 허용한다면, 자식 클래스에서 상속을 통해 접근이 가능하다.
상속 관계를 형성하기 위한 두 클래스는 IS-A 관계에 있어야 한다.
class BusinessMan extends Man { ... }
Man man = new BusinessMan();
부모 클래스의 참조변수는 자식 클래스의 인스턴스를 참조할 수 있고, 부모 클래스에 정의된 메서드는 호출 가능하지만 자식 클래스에만 정의된 메서드 호출은 불가능하다.
위의 코드를 예로 들면 변수 man은 BusinessMan 클래스의 인스턴스를 참조할 수 있고, man 인스턴스는 Man 클래스에 정의된 메서드는 호출 가능하지만, BusinessMan 클래스에만 정의된 메서드는 호출이 불가능한다.
참조하는 인스턴스가 아닌 참조변수의 타입에 제한되는 이유는 다음과 같다.
- 실행 시간을 늦추는 결과로 이어질 수 있다 : 참조 변수의 타입을 참조해 메서드 호출 가능성 판단은 속도가 빠르나, 실제 참조하는 인스턴스를 대상으로 호출 가능성 판단은 쉽지 않다.
- 참조변수의 타입을 기준으로 접근 가능한 멤버를 제한하는 것은 코드를 단순하게 한다.
자바는 참조변수의 형 정보를 기준으로 대입의 가능성을 판단한다.
상속과 생성자
자식 클래스의 인스턴스 생성 시, 부모 클래스의 생성자가 먼저 호출되고, 자식 클래스의 생성자가 호출된다.
자식 클래스의 생성자에서 부모 클래스의 생성자를 명시적으로 호출하지 않으면, 인자를 받지 않는 생성자가 자동으로 호출된다.
오버라이딩
부모 클래스의 메서드를 자식 클래스에서 재정의하여 사용할 수 있는데, 이 기능을 메서드 오버라이딩이라고 한다.
메서드의 이름, 반환형, 매개변수 선언이 모두 같아야 메서드 오버라이딩이 성립한다.
자식 클래스에서 상위 클래스에 정의된 메서드, 즉 오버라이딩 된 메서드의 호출을 할 수 있다. super.(메서드 명) 를 사용하면 자식 클래스 내부에서 부모 메서드를 호출할 수 있다.
만약 부모 클래스와 자식 클래스에 이름이 동일한 변수가 있다고 하자. 변수는 오버라이딩 대상이 아니므로, 참조변수의 형에 따라 접근하는 변수가 결정된다.
@Override 어노테이션을 통해 컴파일 과정에서 확인되지 않는 오류 발생을 차단할 수 있다.
상속의 목적
상속을 통해 연관된 일련의 클래스들에 대해 공통적인 규약을 정의할 수 있다.
자바의 모든 클래스는 Object를 직,간접적으로 상속한다. Object를 최상위 객체로 설정함으로써 자바의 모든 인스턴스에 공통된 기준 및 규약을 적용할 수 있다. 그 예로 public void println() 이나 public String toString() 가 있다.
final 키워드를 클래스나 메서드에 붙게 되면, 클래스는 상속이 불가능하게 되고 메서드는 오버라이딩 할 수 없게 된다.
참조
윤성우의 열혈 JAVA 프로그래밍