상속
목표
자바의 상속에 대해 학습.
목차
- 자바 상속의 특징
- super 키워드
- 메소드 오버라이딩
- 다이나믹 메소드 디스패치 (Dynamic Method Dispatch)
- final 키워드
- Object 클래스
class Man {
public String name;
public void tellYourName() { ... }
}
class BusinessMan extends Man {
public String company;
public void tellYourInfo() {...}
}
extends 키워드로 클래스를 상속한다.
위의 코드에서 BusinessMan bm = new BusinessMan(); 으로 하위 클래스인 businessMan 클래스의 인스턴스를 생성하면,
상위 클래스인 Man 클래스의 인스턴스 멤버들 모두 인스턴스로 할당된다.
상속의 목적
많은 자바 기본서에서는 "자바에서의 상속은 기존의 클래스를 재활용하여 새로운 클래스를 작성하기 위한 문법" 으로 설명하고 있으나 상속을 재활용 관점에서 바라보는 것 문제가 될 수 있다.
상속은 재활용의 측면에서 바라보는 것은 매력적이지 않고, 상속을 통해 연관된 일련의 클래스에 한 공통적인 규약을 정의할 수 있다는 측면에서 사용해야 할 것이다.
상속을 위한 관계
상속으로 클래스의 관계를 구성하기 위해서는 조건이 필요하다.
그리고 조건과 필요가 충족되지 않으면 상속은 하지 않는것만 못하다는 의견이 지배적이다.
상속의 기본 문법에서 보이듯이, 하위 클래스는 상위 클래스가 지니는 모든 것을 지니고
거기에다가 하위 클래스만의 추가적인 특성이 더해진다.
현실 세계로 예를 들면 컴퓨터, 노트북, 태블릿으로 예를 들 수 있다.
노트북은 일종의 컴퓨터이다. 그리고 태블릿도 일종의 컴퓨터이다.
이러한 관계를 IS-A 관계라 한다.
즉 상속관계가 성립하려면 상위 클래스와 하위 클래스에 IS-A 관계가 성립해야 한다.
super("Man", 1, true);
상위 클래스 생성자의 매개변수를 전달하여 상위 클래스의 생성자를 호출한다.
상위 클래스의 인스턴스 변수의 초기화는 인스턴스 변수가 선언된 클래스의 생성자를 통해서 진행하는 것이 가장 좋은 모델이다. 만약에 상위 클래스의 인스턴스 변수에 대한 초기화가 상위 클래스의 생성자를 통해서 진행되지 않으면, 상위 클래스를 상속하는 모든 하위 클래스가 상위 클래스의 인스턴스 변수를 초기화해야하는데, 이는 매우 부담스러운 일이다.
super 키워드로 하위 클래스에서 오버라이딩 된 상위 클래스의 메서드를 호출할 수 있다.
super 키워드로 상위 클래스의 변수, 메서드를 호출할 수 있다.
■ 상위 클래스의 참조변수로도 하위 클래스의 인스턴스를 참조할 수 있다.
※ 우선!
• 상위 클래스의 참조변수는 하위 클래스의 인스턴스를 참조할 수 있다.
• 오버라이딩 된 상위클래스의 메서드는 오버라이딩 된 하위클래스의 메서드에 의해 가리워진다.
즉, 외부에서는 참조변수를 통해서 오버라이딩 된 상위 클래스의 메서드를 호출할 수 없다.
AAA ref1 = new BBB();
• 실제로 참조하는 인스턴스의 종류에 상관없이 참조변수의 자료형으로 선언된 클래스에 정의된 메소드만 호출 가능하다.
• 아래의 관계에서 참조변수의 자료형에 상관없이
마지막으로 오버라이딩을 한 메소드(CCC 클래스의 rideMethod)만 호출된다.
Class AAA{rideMethod()}
Class BBB extends AAA{rideMethod()}
Class CCC extends BBB{rideMethod()}
AAA ref1 = new CCC();
BBB ref2 = new CCC();
CCC ref3 = new CCC();
ref1.rideMethod();
ref2.rideMethod();
ref3.rideMethod();
[참조변수의 인스턴스 참조와 instanceof 연산자]
■ instanceof 연산자
A instanceof B
"A가 B로 형변환이 가능한다면"은 "A가 참조하는 인스턴스가 B, 또는 B를 상속하는 클래스의 인스턴스라면"
Instanceof 연산자는 상속관계를 바탕으로 형변환이 가능한지를 판별하는 연산자이고
boolean형식으로 반환한다.
클래스의 final
상수를 선언하는데 있어서 final이 사용되었다.
클래스를 final로 선언하면 "이 클래스를 상속하는 것을 허용하지 않음"을 의미한다.
개발자가 해당 클래스의 상속이 적절하지 않다고 판단이 될 때 클래스를 final 키워드로 선언한다.
대표적인 final 클래스로는 String 클래스가 있다.
메서드의 final
메서드를 final로 선언하면 "이 메서드의 오버라이딩을 허용하지 않음" 을 의미한다.
이 메서드가 속해있는 클래스를 상속이 가능하다 하더라도 이 메서드의 오버라이딩은 불가능하다.
대표적인 final 메서드로는 Object 클래스의 wait, notify, notifyall 메서드 등이 있다.
이러한 메서드의 오버라이딩은 안전상의 이유로도 바람직하지 않다.
모든 클래스가 상속하는 Object 클래스
클래스를 정의할 때 다른 어떤 클래스도 상속하지 않으면,
해당 클래스는 java.lang 패키지에 묶여있는 Object 클래스를 상속하게 된다.
따라서 모든 클래스는 직접적으로, 간접적으로 Object 클래스를 상속하고 있는 것이다.
여기서 간접적으로 Object 클래스를 상속한다는 것은 어떤 하위 클래스의 최상위 클래스는 Object클래스를 상속함을 의미한다.
모든 클래스가 Object 클래스를 상속하도록 한 이유?
자바의 모든 인스턴스에 공통된 기준을 적용하기 위함이다.
toString 메서드를 기준으로 예를 들면, 자바의 Object 클래스에는 다음의 메서드가 정의되어 있다.
public String toString();
그리고 System.out.println은 오버로딩 되어있는 메서드인데, 그중 하나가 아래와 같이 정의되어 있기 때문에 어떠한 클래스의 인스턴스이건 인자로 전달될 수 있다.
public void println(Object x)
참고 서적 : 난 정말 JAVA를 공부한 적이 없어요 (ORANGE MEDIA 윤성우 저)