Notice
Recent Posts
Recent Comments
«   2024/09   »
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 30
Archives
Today
Total
관리 메뉴

충분히 쌓여가는

추상 클래스(abstract class), 추상 메서드(abstract method) 본문

Java/객체지향

추상 클래스(abstract class), 추상 메서드(abstract method)

빌드이너프 2023. 6. 13. 23:59

추상 클래스

미완성 설계도, 미완성 메서드를 갖고 있는 클래스

추상 메서드를 가지고 있는 클래스에 abstract라는 키워드를 붙이고 추상 클래스라고 한다

abstract class Player { // 추상클래스(미완성 클래스)
    abstract void play(int pos); // 추상메서드(몸통 {}이 없는 미완성 메서드)
    abstract void stop(); // 추상클래스
}

 

추상 클래스는 다른 클래스 작성에 도움을 주기 위한 것으로, 인스턴스 생성 불가능하다

추상 클래스의 Player의 객체를 만드는 것이 불가능하다(아직 설계도가 완성되지 않았기 때문)

Player p = new Player(); // 에러, 추상 클래스의 인스턴스 생성 불가

 

상속을 통해 추상 메서드를 완성해야 인스턴스 생성 가능하다(추상 메서드가 아니면 abstract 제거)

추상 메서드 구현: 추상 메서드 몸통{} 만들기

타입으로 Player 가능(조상 타입), 다형성 때문에 가능함[호출할 경우 Player.play     Player.stop]

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

AudioPlayer ap = new AudioPlayer(); // 인스턴스 생성 OK, 객체 생성 OK
// Player ap = new AudioPlayer(); // 다형성, 조상 Player OK

 

추상 메서드(=미완성 메서드)

몸통{}, 구현부가 없는 미완성 클래스(메서드 = 선언부(O) + 구현부(X))

몸통 {}이 없기 때문에 abstract라는 키워드를 붙여준다

이 추상 메서드를 가지고 있는 클래스를 추상 클래스라고 한다

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

 

추상 메서드 사용시기

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

 

AudioPlayer은 추상 메서드 2개 중 2개를 다 구현했기 때문에 abstract를 제거해주고, 

AbstractPlayer은 추상 메서드 2개 중 1개만 구현했기 때문에 abstract가 존재한다

abstract class Player { // 추상 클래스
    abstract void play(int pos); // 추상 메서드
    abstract void stop(); // 추상 메서드
}

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

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

 

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

play와 stop라는 메서드를 abstract(추상화)해두면 두 메서드가 구현이 아직 안되어있어 상속을 받을경우 두 메서드를 완성해야하는 것을 알려줄 수 있다

abstract class Player {
    boolean pause;// 일시정지 상태를 저장하기 위한 변수
    int currentPos; // 현재 Play되고 있는 위치를 저장하기 위한 변수
    
    Player() { // 추상 클래스도 생성자가 있어야한다
        pause = false;
        currentPos = 0;
    }
    
    abstract void paly(int pos); // 추상 메서드
    abstract void stop(); // 추상 메서드
    void play() {
        play(currentPos); // 추상 메서드 호출 불가능
    }
}

 

여기서 아직까지 void play() { }라는 instance 메서드를 호출할 수 없다

호출 가능한 경우: 현재 몸통{}이 없지만 상속을 통해 자손이 완성한다면 호출 가능하다

void play() {}는 인스턴스 메서드이기 때문에 객체를 생성한 후 사용할 수 있고, 현재는 추상클래스라서 객체 생성이 불가능하다

void play() {
    play(currentPos);
}

 

void play() {}를 호출하기 위해 필요한 것

1. 상속을 통해 자손(DvdPlayer)이 구현부, 즉 몸통{}을 완성

2. 자손 객체 생성

DvdPlayer d = new DvdPlayer();
d.play();

 

따라서 자손을 통해 해당 instance 메서드를 완성했다면

추상 클래스라도 void paly() { play(currentPos); }이 호출가능하다

abstract class Player {
    boolean pause;// 일시정지 상태를 저장하기 위한 변수
    int currentPos; // 현재 Play되고 있는 위치를 저장하기 위한 변수
    
    Player() { // 추상 클래스도 생성자가 있어야한다
        pause = false;
        currentPos = 0;
    }
    
    abstract void paly(int pos); // 추상 메서드
    abstract void stop(); // 추상 메서드
    void play() {
        play(currentPos); // 추상 메서드 호출 가능
    }
}


추상 클래스만 있을 때 객체 생성

에러 발생

abstract class Player { // 추상 클래스(미완성 클래스, 미완성 설계도)
    abstract void play(int pos); // 추상 메서드(미완성 메서드)
    abstract void stop(); // 추상 메서드(선언부만 있고 구현부{}가 없는 메서드)
}


public class PlayerTest {
    public static void main(String[] args) {
        Player p = new Player(); // 에러, 추상 클래스의 객체 생성
    }
}

 

상속 후

abstract class Player { // 추상 클래스
    abstract void play(int pos); // 추상 메서드
    abstract void stop(); // 추상 메서드
}

// 추상 클래스는 상속을 통해 완성해야 객체 생성 가능
class AudioPlayer extends Player {
    void play(int pos) {} // 둘 다 구현 해야 오류 안뜸
    void stop() {} // 둘 다 구현 해야 오류 안뜸
}

public class PlayerTest {
    public static void main(String[] args) {
        AudioPlayer ap = new AudioPlayer();
    }
}

 

실행까지

abstract class Player { // 추상 클래스
    abstract void play(int pos); // 추상 메서드
    abstract void stop(); // 추상 메서드
}

// 추상 클래스는 상속을 통해 완성해야 객체 생성 가능
class AudioPlayer extends Player {
    void play(int pos) { System.out.println(pos); }
    void stop() { System.out.println("재생 중지");}
}

public class PlayerTest {
    public static void main(String[] args) {
        AudioPlayer ap = new AudioPlayer();
        ap.play(100);
        ap.stop();
    }
}

100
재생 중지

 

다형성 사용

AudioPlayer를 조상인 Player로 받는다

abstract class Player { // 추상 클래스
    abstract void play(int pos); // 추상 메서드
    abstract void stop(); // 추상 메서드
}

// 추상 클래스는 상속을 통해 완성해야 객체 생성 가능
class AudioPlayer extends Player {
    void play(int pos) { System.out.println(pos); }
    void stop() { System.out.println("재생 중지");}
}

public class PlayerTest {
    public static void main(String[] args) {
        Player ap = new AudioPlayer(); // 다형성
        ap.play(100);
        ap.stop();
    }
}

100
재생 중지

 

Player로 해도 리모컨이기 때문에 그림으로 표현하면 이렇게 된다

Player이 추상 메서드라도 실제 연결된 것은 구현된 AudioPlayer이 실행된다

즉, Player에 있는 play()와 stop()이 실행되는 것이 아니라 AudioPlayer에 있는 play()와 stop()가 실행된다

(참조변수 타입과 무관하다)