추상클래스(abstract class)
추상클래스란?
o 추상 클래스는 미완성 설계도로 비유할 수 있다. 미완성이라는 것은 멤버 개수에 관계된 것이 아닌 미완성 메서드(추상메서드)를 포함하고 있다는 의미이다.
o 추상클래스는 인스턴스를 생성할 수 없으며, 상속을 통해 자손클래스에 의해서만 완성될 수 있다. 추상클래스 자체로는 클래스로서 역할을 다 못하지만, 새로운 클래스를 작성하는데 있어 중요한 의미를 갖는다.
o 키워드 ‘abstract’를 붙이기만 하면 추상클래스를 선언할 수 있다. 이를 통해 이 클래스에는 추상메서드가 있으니 상속을 통해 구현을 해줘야 한다는 것을 쉽게 알 수 있다.
abstract class Ex {...}
o 추상 클래스는 추상 메서드를 포함하고 있다는 것을 제외하면 일반 클래스와 다르지 않다. 생성자, 메서드, 매개 변수도 가질 수 있다.
추상메서드(abstract method)
o 추상메서드는 메서드의 선언부만 작성하고 구현부는 작성하지 않은 메서드이다. 메서드 내용이 상속받는 클래스에 따라 달라질 수 있기에 조상클래스에서는 선언부만 작성하고, 주석을 붙여 어떤 기능을 수행할 목적인지 알려준다. 실제 내용은 상속받는 클래스에서 구현하도록 비워 두는 것이다.
o 추상메서드 역시 키워드 ‘abstract’를 붙여주고 괄호 { }대신 세미콜론(;)을 붙여준다.
o 추상클래스로부터 상속받는 자손클래스는 오버라이딩을 통해 조상인 추상클래스의 추상 메서드를 모두 구현해야 한다. 만약 조상으로부터 상속받은 추상 메서드를 하나라도 구현하지 않는다면 해당 자손 클래스는 추상 클래스로 지정해줘야 한다.
abstract class Player { // 추상클래스
abstract void play(int pos); //추상 메서드
abstract void stop();
}
class AudioPlayer extends Player {
void play(int pos) { } //상속받은 추상 메서드 구형
void stop() { }
}
//추상 메서드를 하나라도 구현하지 않을 시 abstract class로 지정
abstract class AbstractPlayer extends Player{
void play(int pos) { }
}
|
추상클래스의 작성
o 상속이 자손 클래스를 만드는데 조상 클래스를 사용하는 것이라면, 이와 반대로 추상화는 기존의 클래스의 공통부분을 뽑아내서 조상클래스를 만드는 것이다.
o 상속계층도를 따라 내려갈수록 클래스는 세분화되며, 올라갈수록 공통요소만 남게 된다.
추상[抽象] |
낱낱의 구체적 표상이나 개념에서 공통된 성질을 뽑아 이를 일반적인 개념으로 파악하는 정신 작용 |
추상화 |
클래스 간의 공통점을 찾아내서 공통의 조상을 만드는 작업 |
구체화 |
상속을 통해 클래스를 구현, 확장하는 작업 |
abstract class Player {
boolean pause; //일시정지를 위한 변수
int currentPos; // 현재 play위치 저장 변수
Player() { //추상클래스도 생성자가 있어야 한다.
pause = false;
currentPos = 0;
}
/*지정된 위치에서 재생을 시작하는 기능이 수행하도록 작성*/
abstract void play(int pos);
/*재생을 즉시 멈추는 기능을 수행하도록 작성*/
abstract void stop();
void play() {
play(currentPos); // 추상메서드를 사용 할 수 있다.
}
void pauser() {
if(pause) { // pause 상태가 true이면 false로 변경 후 현재위치 play 실행
pause = false;
play(currentPos);
} else { // pause 상태가 true이면 true로 변경 후 play 중지
pause = true;
stop();
}
}
}
class CDPlayer extends Player {
void play(int por) {/*조상의 추상메서드 구현, 내용생략*/}
void stop() {/*조상의 추상메서드 구현, 내용생략*/}
//CDPlayer에 추가 정으된 멤버
int currentTrack; // 현재 재생중인 트랙
void nextTrack() {
currentTrack++;
}
void preTrack() {
if(currentTrack>1) {
currentTrack--;
}
}
}
|
- 조상클래스의 추상 메서드를 CDPlayer클래스 기능에 맞게 완성해주고, CDPlayer만의 새로운 기능을 추가하였다.
o 조상 클래스의 추상 메서드를 일반 메서드로 구현해서 자손 클래스에서 오버 라이딩하여 사용할 수도 있다. 굳이 abstract를 붙여 추상메서드를 선언하는 이유는 자손 클래스에서 추상 메서드를 반드시 구현하도록 강요하기 위해서다. 만약 빈 구현부만 있는 메서드를 일반 메서드로 한다면 상속받는 자손클래스는 이 메서드가 온전히 구현된 것으로 인식하여 오버라이딩을 통해 자신의 클래스에 알맞게 구현하지 않을 수도 있다.
추상화 전 |
추상화 후 |
||
|
|
- 공통 부분을 뽑아내서 Unit클래스로 정의하고 상속받도록 했다. stop( )메서드는 공통이지만 이동 수단이 달라 move( )에서 다르게 정의할 것 이기에 제외하였다.
- move 메서드가 추상 메서드로 선언됨에 따라 앞으로 Unit클래스를 상속받는 클래스는 move메서드를 반드시 구현해야 한다는 의미가 있다.
o 작성한 코드는 조상 클래스타입의 참조변수로 자손 클래스의 인스턴스를 참조하는 것이 가능하기에 조상 클래스 타입의 참조 배열로 담을 수 있다. 만약 공통된 조상 클래스가 없다면 하나의 배열로 다룰 수 없을 것이다.
o move메서드는 추상 메서드라도 참조변수로 호출하는 것이 가능한데, 메서드는 참조변수 타입 관계없이 실제 인스턴스에 구현된 것이 호출되기 때문이다. 즉, 조상 클래스(Unit)의 추상 메서드(move)를 호출하는 것이 아니라 실제 이 추상 메서드가 구현된 자손 클래스(Marine, Tank, Dropship)의 메서드가 호출되는 것이다.
|
|
||
- 클래스들의 공통 조상인 Unit클래스 타입으로 묶어주었다. - Unit클래스 타입의 참조 변수를 통해 move메서드를 호출이 가능하다. |
- 모든 클래스 조상인 Object 타입의 배열로도 서로 다른 종류의 인스턴스를 묶을 수 있다. - 그러나 Object클래스에는 move메서드가 정의되어 있지 않기에 move메서드 호출 시 에러가 발생한다. |
'언어 > 자바의 정석' 카테고리의 다른 글
[07-8] 내부 클래스(inner class), 익명 클래스(anonymous class) (0) | 2021.02.17 |
---|---|
[자바의 정석] Chapter 7 객체 지향 프로그래밍II (8) - 인터페이스(interface) (0) | 2021.02.17 |
[자바의 정석] Chapter 7 객체 지향 프로그래밍II (6) - 다형성(polymorphism)(2) (0) | 2021.02.16 |
[자바의 정석] Chapter 7 객체 지향 프로그래밍II (5) - 다형성(polymorphism) (0) | 2021.02.16 |
[자바의 정석] Chapter 7 객체 지향 프로그래밍II (4) - 제어자(modifier) (0) | 2021.02.16 |