추상클래스(Abstract Class)는 인터페이스의 역할도 하면서 구현체도 가지고 있는 자바의 돌연변이 클래스라고 한다. 혹자는 추상 클래스는 인터페이스로 대체하는것이 좋은 디자인라고도 얘기한다. - 점프 투 자바 블로그-
간단하게 추상 클래스를 살펴보기 전에 특징부터 알아보도록 하자
- 추상 메소드가 하나 이상 포함되면 반드시 추상 클래스로 선언되어야 한다.
- 반드시 추상 클래스를 상속하는 자식 클래스에서 부모가 가진 추상 메소드를 모두 오버라이딩 해야 한다.
- 추상 클래스에서 추상 메소드가 아닌 일반 메소드를 포함시킬 수 있다.
- 추상 메소드는 몸체가 없고 선언부만 존재한다.
추가로 추상 클래스는, 상속 관계에서 어느 메소드를 오버라이딩 할때 사용된다. 추상메소드, 추상클래스는 abstract 키워드를 사용하여 알려줄 수 있다.
다음은 추상클래스를 선언하는 방법이다.
abstract 클래스명 {
...
abstract void 메소드명();
}
위에서 추상 메소드를 보면 이미 말했듯이 몸체는 없고 선언부만 존재한다. 이는 자식 클래스들의 특징이 서로 다를때 메소드를 미완성 메소드로 남겨두어 부모 클래스를 상속한 자식 클래스에서 각각의 기능을 구현할 수 있도록 한것이다. 추상클래스는 추상메서드를 포함하고 있다는 것을 제외하고는 일반클래스와 전혀 다르지 않다. 추상클래스에도 생성자가 있으며, 멤버변수와 일반 메서드도 가질 수 있다.
[참고] 추상메서드 포함하고 있지 않은 클래스에도 키워드 'abstract'를 붙여서 추상클래스로 지정할 수도 있다. 추상 메소드가 없는 완성된 클래스라 할지라도 추상클래스로 지정되면 클래스의 인스턴스를 생성할 수 없다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | [자바의 정석] abstract class Player { boolean pause; // 일시정지상태를 저장하기 위한 변수 int currentPos; // 현재 Play되고 있는 위치를 저장하기 위한 변수 Player() { // 추상클래스도 생성자가 있다. pause = false; currentPos = 0; } /** 지정된 위치(pos)에서 재생을 시작하는 기능이 수행하도록 작성되어야 한다. */ abstract void play(int pos); // 추상메서드 /** 재생을 즉시 멈추는 기능을 수행하도록 작성되어야 한다. */ abstract void stop(); // 추상메서드 void play() { play(currentPos); // 추상메서드를 사용할 수 있다. } void pause() { if(pause) { // pause가 true일 때(정지상태)에서 pause가 호출되면, pause = false; // pause의 상태를 false로 바꾸고, play(currentPos); // 현재의 위치에서부터 play를 한다. } else { // pause가 false일 때(play상태)에서 pause가 호출되면, pause = true; // pause의 상태를 true로 바꾸고 stop(); // play를 멈춘다. } } } | cs |
이제 Player클래스를 조상으로 하는 CDPlayer 클래스를 만들어보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | class CDPlayer extends Player { // 조상 클래스의 추상메서드를 구현한다. void play(int currentPos) { /* 실제구현 내용 생략 */ } void stop() { /* 실제구현 내용 생략 */ } // CDPlayer클래스에 추가로 정의된 멤버 int currentTrack; // 현재 재생 중인 트랙 void nextTrack() { currentTrack++; //... } void preTrack() { if(currentTrack > 0) { currentTrack--; } //... } } | cs |
1 2 3 4 5 6 | class Player { ... void play(int pos) {} void stop() {} ... } | cs |
어차피 자손클래스에서 오버라이딩하여 자신의 클래스에 맞게 구현할 테니 추상메서드로 선언하는 것과 내용없는 빈 몸통만 만들어 놓는 것이나 별 차이가 없어 보인다.
굳이 abstract를 붙여서 추상메서드로 선언하는 이유는 자손클래스에서 추상메서드를 반드시 구현하도록 강요하기 위해서이다.
만일 추상메서드로 정의되어 있지 않고 빈 몸통만 가지도록 정의되어 있다면, 상속받는 자손클래스에서는 이 메소드들이 온전히 구현된 것으로 인식하고 오버라이딩을 통해 자신의 클래스에 맞도록 구현하지 않을 수도 있기 때문이다.
하지만 abstract를 사용하여 추상메서드로 정의해놓으면, 자손클래스를 작성할 때 이들이 추상메서드이므로 내용을 새로 구현해주어야 한다는 사실을 인식하고 자신의 클래스에 알맞게 구현할 것이다.
'Dev > JAVA ' 카테고리의 다른 글
JAVA Split "|" 제거 방법 (0) | 2018.05.17 |
---|---|
JAVA 다형성 (1) | 2018.01.17 |
JAVA 인터페이스(Interface) (0) | 2018.01.15 |
JAVA 상속 (2) | 2018.01.12 |
[JAVA] jsp / java를 이용한 DB연동 (0) | 2017.12.04 |