목적
자바의 상속에 대해 학습하세요.
학습할 것
- 자바 상속의 특징
- super 키워드
- 메소드 오버라이딩
- 다이나믹 메소드 디스패치 (Dynamic Method Dispatch)
- 추상 클래스
- final 키워드
- Object 클래스
1. 자바 상속의 특징
자바의 상속 전, 상속이란, 기존 클래스를 재사용하여 새로운 클래스를 작성하는 것이다. 이는 코드의 재사용성을 높이고 중복을 제거하여 생산성과 유지성에 크게 기여한다.
-
단일 상속
다른 객체지향 언어인 C++ 에서는 여러 조상 클래스로부터 상속받는 것이 가능한 ‘다중상속’을 허용하지만, 자바는 오직 단일 상속만 허용한다. 만약 다중 상속을 허용하게 된다면 클래스 내 인스턴스 메서드를 구별할 방법이 없다. 이처럼 명확하고 신뢰성 있는 코드를 위해 다중 상속의 장점을 포기하며 단일 상속을 지원한다.
-
상속 횟수 제한 X
자바에서는 상속에 제한을 두지 않는다.
-
최상의 클래스
자바에서는 모든 상속계층도의 최상위에 Object 클래스가 위치한다. 따라서 Object 클래스에 정의된 멤버들을 사용할 수 있다.
2. super 키워드
super란 자손 클래스에서 조상 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조변수이다.
멤버변수와 지역변수의 이름이 같을 때 this를 붙여서 구별했듯이, 상속받은 멤버와 자신의 멤버가 같을 떈 super를 붙여서 구별한다.
조상 클래스 멤버와 자손 클래스의 멤버가 중복 정의되어 서로 구별해야 하는 경우에만 super를 사용하는 것이 좋다.
super는 static 메서드에선 사용할 수 없다.
조상 클래스에서 선언된 멤버변수와 같은 이름의 멤버변수를 가진 자손 클래스엔 중복되게 정의가 가능하며 super를 사용해 구별해준다.
메서드 역시 super를 사용하여 호출할 수 도있다.
ex) super.getName();
생성자에서는 super()는 생성자이고 조상 클래스의 생성자를 호출하는데 사용된다. 그리고 자손 클래스의 멤버가 조상 클래스의 멤버를 사용할 수 있으므로 조상의 멤버가 먼저 초기화 되어야 한다. (super() 가 가장 먼저 선언되어야 하는 이유) 혹시나 적어놓지 않았으면 컴파일러가 자동으로 추가해준다.
만약 조상 클래스의 값들을 가지고 생성자를 호출하고 싶다면 super(변수, 변수 …) 이런 식으로 호출하면 된다.
3. 메소드 오버라이딩
오버라이딩이란 상속받은 메서드의 내용을 변경하여 사용하는 것이다. 자손 클래스에 맞게 변경해야 하는 경우가 많고 이럴 때 오버라이딩을 사용한다.
오버라이딩의 조건을 성립시키기 위해선 3가지 조건이 맞아야 한다.
- 이름이 같아야 한다.
- 매개변수가 같아야 한다.
- 반환타입이 같아야 한다.
요약하면 선언부가 일치해야 한다고 말할 수 있고 접근 제어자와 예외같은 경우는 제한된 조건이 있다.
- 접근 제어자는 조상 클래스 메서드보다 좁은 범위로 변경할 수 없다.
- 예외는 조상 클래스의 메서드보다 많이 선언할 수 없다.
- 인스턴스메서드와 static 메서드를 서로 변경해서 사용할 수 없다.
(static 같은 경우는 오버라이딩이 아니라 그냥 static 메서드를 정의 한 것이다. )
4. 다이나믹 메소드 디스패치
다이나믹 메소드 디스패치에 대한 정보가 안나와서 나름 다른 분들의 글과 인터넷 검색을 통해서 찾아 보았고 정확한 정보를 알 순 없었다.
허나 일단 글대로 적자면,
다이나믹 메소드 디스패치는 오버라이딩 되어있는 메소드를 실행할 때 런타임 시점에서 어떤 메소드를 실행할 지 결정하려는 것이다.
인터페이스를 참조한 2개의 자식 클래스가 있고, 이에 인터페이스를 생성하여 그 안의 함수를 실행시켰을 때, 과연 2개의 자식 클래스 중 누가 호출되는 것인 지를 컴파일러가 알 수 없는 것이다.
5. 추상 클래스
추상 클래스는 클래스에 정의할 내용을 추상적으로 적어놓은, 즉 설계도의 틀 이라고 생각하면 좋다. 추상클래스는 상속을 통해서 자손 클래스에 의해서만 완성될 수 있다. 추상 클래스는 클래스 앞에 abstract를 붙이면 된다. 긜고 상속을 통해 구현해주면 완성된다. 또한 추상클래스에서도 생성자가 있으며, 멤버변수와 메서드도 가질 수 있다.
abstract class 클래스이름 {
}
스포츠를 예시로 들자면 축구 농구 배구 등이 있고 축구 선수 배구 선수 농구 선수가 있는데 이 3명의 선수는 스포츠 선수라는 타이틀을 가지고 있고 추상화를 통해 스포츠 선수를 정의할 수 있다.
abstract class Player{
boolean pause;
int currentPos;
Player(){
pause = false;
currentPos = 0;
}
abstract void play();
abstract void stop();
}
6. final 키워드
변경될 수 없는 의미를 가지고 있는 의미이며 선언시 변경할 수 없는 상수가 된다.
메서드에 사용 시엔 오버라이딩을 할 수 없고 클래스에 사용하면 자손 클래스를 정의하지 못하게 된다.
final 사용 구간은 클래스, 메서드, 멤버변수, 지역변수 이다.
final이 붙은 변수는 상수이므로 선언과 초기화를 동시에 하지만, 인스턴스 변수의 경우 생성자에서 초기화 되도록 할 수 있다. 클래스 내에 매개변수를 갖는 생성자를 선언하여, 인스턴스를 생성할 때 final이 붙은 멤버변수를 초기화하는데 필요한 값을 생성자의 매개변수로부터 제공받는 것이다. 이를 통해 각 인스턴스마다 final이 붙은 멤버변수가 다른 값을 갖도록 하는 것이 가능하다. 이것이 불가능 하다면 final이 붙은 인스턴스 변수는 모든 인스턴스에서 같은 값이 되어야만 한다.
7. Object 클래스
Obejct 클래스는 모든 클래스의 최상위 위치에 있는 조상 클래스이다.
class Study extends Object{
}
모든 클래스들은 Object 클래스를 상속받고 있다. 이를 통해 모든 클래스는 Object 클래스에 정의된 멤버, 함수들을 사용할 수 있다.
Object 클래스의 메서드 | 설 명 |
---|---|
protected Object clone() | 객체 자신의 복사본을 반환한다. |
public boolean equals(Object obj) | 객체 자신과 객체 obj가 같은 객체인지 알려준다.(같으면 true) |
protected void finalize() | 객체가 소멸될 때 가비지 컬렉터에 의해 자동적으로 호출된다. 이 때 수행되어야하는 코드가 있을 때 오버라이딩 한다.(거의 사용 안함) |
public Class getClass() | 객체 자신의 클래스 정보를 담고 있는 Class인스턴스를 반환한다. |
public int hashCode() | 객체 자신의 해시코드를 반환 |
public String toString() | 객체 자신의 정보를 문자열로 반환 |
public void notify() | 객체 자신을 사용하려고 기다리는 쓰레드를 하나만 깨운다. |
public void notifyAll() | 객체 자신을 사용하려고 기다리는 모든 쓰레드를 깨운다. |
public void wait() public void wait(long timeout) public void wait(long time, int nanos) | 다른 쓰레드가 notify()나 notifyAll()을 호출할 떄까지 현재 쓰레드를 무한히 또는 지정된 시간(timeout, nanos)동안 기다리게 한다. |