JAVA 추상 클래스



추상클래스(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


추상클래스의 추상메서드를 CDPlayer클래스의 기능에맞게 완성해주고, CDPlayer만의 새로운 기능들을 추가했다. 사실 Player클래스의 play(int Pos)와 stop()을 추상메소드로 하는 대신, 아무 내용도 없는 메서드로 작성할 수 도 있다. 아무런 내용도 없이 단지 괄호()만 있을지라도, 추상메서드가 아닌 일반메소드로 간주되기 때문이다.

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