Java의 정석_기초편

추상 클래스(abstract class)

DJDU 2022. 10. 9. 16:29

추상클래스

  • 미완성 설계도. 추상메서드(미완성 메서드)를 가지고 있는 클래스
  • 다른 클래스 작성에 도움을 주기 위한 것. 인스턴스 생성 불가
  • 상속을 통해 추상메서드를 완성해야 인스턴스 생성 가능
더보기

미완성 설계도. 추상메서드(미완성 메서드)를 가지고 있는 클래스

// 미완성 설계도. 추상메서드(미완성 메서드)를 가지고 있는 클래스
abstract class Player {
    abstract void play(int pos);  // 추상 메서드(몸통{}이 없는 미완성 메서드)
    abstract void stop();         // 추상 메서드
}

 

다른 클래스 작성에 도움을 주기 위한 것. 인스턴스 생성 불가

// 새로운 클래스를 작성하는데 있어서 바탕이 되는 조상 클래스. 인스턴스 생성 불가
Player p = new Player();            // 에러. 추상 클래스의 인스턴스 생성 '불가'

 

상속을 통해 추상메서드를 완성해야 인스턴스 생성 가능

// 상속을 통해 추상 메서드를 완성해야 인스턴스 생성 가능
class AudioPlayer extends Player {
     void play(int pos) { /* 내용 생략 */ }  // 추상메서드를 구현
     void stop()        { /* 내용 생략 */ }  // 추상메서드를 구현     
}

AudioPlayer ap = new AudioPlayer(); // OK. 인스턴스 생성 '가능'
/*
Player ap = new AudioPlayer(); // OK. 다형성
*/

 

추상메서드

  • 미완성 메서드. 구현부(몸통, {})가 없는 메서드
  • 꼭 필요하지만 자손마다 다르게 구현될 것으로 예상되는 경우
  • 추상 메서드 호출 가능(호출할 때는 선언부만 필요)
더보기

미완성 메서드. 구현부(몸통, {})가 없는 메서드

abstract 리턴타입 메서드이름();

 

꼭 필요하지만 자손마다 다르게 구현될 것으로 예상되는 경우(에 사용한다)

  • 추상메서드 구현 : 몸통’{}’ 만들기
  • 상속받은 추상메서드를 모두 구현하지 않은 경우, 자손 클래스 선언부 앞에 abstract를 붙여야 한다.
abstact class Player { // 추상클래스
    abstract void play(int pos);  // 추상메서드
    abstract void stop();         // 추상메서드
    
    void play() {                 // 인스턴스 메서드
        play(currentPos);         // 추상메서드를 사용할 수 있다.
    }
} // 메서드는 선언부만 알면 호출가능하므로 추상메서드도 호출 가능하다.

class AudioPlayer extends Player {
    void play(int pos) { /* 내용 생략 */ }  // 추상메서드를 구현 
    void stop()        { /* 내용 생략 */ }  // 추상메서드를 구현
}

abstract class AbstractPlayer extends Player {  // 추상메서드 1개만 구현(미완성)
    void play(int pos) { /* 내용 생략 */ }        // 추상메서드를 구현
}                                               // abstract void stop(); 이 생략됨

/*
추상메서드 구현 : 몸통({}) 만들어주기
*/

 

im : 추상 메서드 호출 가능(호출할 때는 선언부만 필요하기 때문)

 

추상메서드 호출 조건

  1. 상속을 통해 자손이 완성
  2. 자손 객체 생성
  • 인스턴스메서드는 객체 생성 후 호출 가능하다.
  • 하지만, 지금은 추상클래스이기 때문에 객체 생성이 불가하다.
  • 따라서, 지금은 추상클래스의 인스턴스메서드에 호출하는 코드가 있어도 호출할 수 없다.
  • 상속을 통해 자손이 추상메서드를 구현한 후, 자손 객체 생성 후 추상메서드를 호출할 수 있게 된다.
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);         // 추상메서드를 사용할 수 있다.
    }
}

 

예제 - PlayerTest

더보기
abstract class Player {
	abstract void player(int pos); // 추상메서드(미완성 메서드)
	abstract void stop();          // 추상메서드(선언부만 있고 구현부{}가 없는 메서드)
}

// 추상 클래스는 상속을 통해 완성해야 객체 생성 가능
class AudioPlayer extends Player {
	void player(int pos) { System.out.println(pos + "위치부터 play합니다.");}
	void stop() { System.out.println("재생을 멈춥니다.");}
}

public class PlayerTest {
	public static void main(String[] args) {
//		Player p = new Player(); // 추상클래스의 객체를 생성
//		AudioPlayer ap = new AudioPlayer();
		Player ap = new AudioPlayer(); /// 다형성
		ap.player(100);
		ap.stop();
	}
}

 

  • 리모컨이 아무리 추상메서드라고 해도 실제로 구현된 메서드가 실행된다.
  • Player타입의 참조변수가 메서드를 호출하면 실제 객체의 play메서드가 호출된다.
  • 리모컨 타입에는 선언문만 있으면 된다.

 

다형성

 

 

 

추상클래스의 작성

  • 여러 클래스에 공통적으로 사용될 수 있는 클래스를 바로 작성하거나, 기존클래스의 공통 부분을 뽑아서 추상클래스를 만든다.
더보기

여러 클래스에 공통적으로 사용될 수 있는 클래스를 바로 작성하거나,
기존클래스의 공통 부분을 뽑아서 추상클래스를 만든다.

 

 

추상화 ↔ 구체화

  • 추상화 : 불명확, 애매
  • 구체화 : 명확함, 구체적
  • 추상화된 코드는 구체화된 코드보다 유연하다. 변경 포인트 ↓  : 변경에 유리
더보기

추상화된 코드는 구체화된 코드보다 유연하다. 변경 포인트 ↓  : 변경에 유리

GregorianCalendar cal = new GregorianCalendar();    // 구체적
Calendar cal = Calendar.getInstance();              // 추상적
/*
    Calendar : 추상 클래스
*/

 

실습 : Ex7_10

더보기

모든 클래스의 조상인 Object클래스 타입의 배열로도 서로 다른 종류의 인스턴스를 하나의 묶음으로 다룰 수 있다. 하지만, Object클래스에는 move메서드가 정의되어 있지 않기 때문에 move메서드를 호출하는 부분에서 에러가 발생한다.

 

Object[] group = new Object[3];
group[0] = new Marine();
group[1] = new Tank();
group[2] = new Dropship();

for(int i = 0; i < group.length; i++)
	group[i].move(100, 200)    // 에러!!!! Object클래스에 move메서드가 정의되어 있지 않다.

 


🍪