{}
, 즉 구현부가 없다.()
뒤에 ;
를 붙이기abstract class Player {
abstract void play(int pos); //{}가 없다.
abstract void stop(); //추상메소드
}
Player p = new Player(); //에러
class AudioPlayer {
void play(int pos) { */내용*/ } //추상메소드를 완성
void stop(int pos) { */내용*/ } //그러므로 abstract도 뗐고 클래스도 더이상 추상클래스가 아니다.
}
AudioPlayer ap = new AudioPlayer(); //완성이므로 가능
Player ap = new AudioPlayer();
//가능✨✨ 리모콘이 완성인 AudioPlayer를 가리키므로
일부만 구현해도 된다. 그럴 경우 abstract
꼭 붙이기!!
추상메소드 사용의 이유 : 꼭 필요하지만 자손마다 다르게 구현될 것으로 예상되는 경우
필수 기능일 경우 abstract
를 붙여 강제성을 보여준다. -> 자손클래스에서 이 필수적인 메소드를 완성시켜라!!
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 p = new Player(); //추상클래스로 객체못만듦, 에러
AudioPlayer ap = new AudioPlayer();
ap.play(100);
ap.stop();
Player p = new AudioPlayer(); //추상클 타입은 선언은 됨! 실제 생성된 객체는 AP니까 상관없음
p.play(200);
p.stop();
}
}
100위치부터 플레이시작합니다.
정지합니다.
200위치부터 플레이시작합니다.
정지합니다.
ch07Re2_PlayerTest
abstract class Player{
int currentPos;
boolean pause;
public Player() {
super(); //생성자 첫줄에 생성자 호출 없으면 자동 추가
currentPos = 0;
pause = false;
}
abstract void play(int pos);
abstract void stop();
void play() {
play(currentPos);
};
}
class AudioPlayer extends Player{
public AudioPlayer() { //자동추가
super(); //자동추가
}
@Override
void play(int pos) {
currentPos = pos;
System.out.println(currentPos+"에서 재생을 시작합니다.");
}
@Override
void stop() {
pause = true;
System.out.println("멈춥니다.");
}
void status() {
System.out.println("현재 pause 상태: "+pause);
}
}
public class PlayerTest {
public static void main(String[] args) {
AudioPlayer ap = new AudioPlayer();
ap.status();
ap.play();
ap.play(10);
ap.stop();
ap.status();
System.out.println("--------");
Player p = new AudioPlayer();
// p.status(); 리모콘x, 형변환 후 사용 가능
((AudioPlayer) p).status(); //이때 한번만임
p.play();
p.play(20);
p.stop();
((AudioPlayer) p).status();
}
}
현재 pause 상태: false
0에서 재생을 시작합니다.
10에서 재생을 시작합니다.
멈춥니다.
현재 pause 상태: true
--------
현재 pause 상태: false
0에서 재생을 시작합니다.
20에서 재생을 시작합니다.
멈춥니다.
현재 pause 상태: true
여러 클래스에서 공통적으로 사용될 수 있는 추상클래스를 바로 작성하거나
기존클래스의 공통 부분을 뽑아서 추상클래스를 만든다.
class Marine{ //보병
int x, y; //현재 위치
void move(int x, int y) {/*지정된 위치로 이동*/}
void stop() {/*현재 위치에 정지*/}
void stimPack() {/*스팀팩을 사용*/}
}
class Tank{ //탱크
int x, y; //현재 위치
void move(int x, int y) {/*지정된 위치로 이동*/}
void stop() {/*현재 위치에 정지*/}
void changeMode() {/*공격모드를 변환*/}
}
class DropShip{ //수송선
int x, y; //현재 위치
void move(int x, int y) {/*지정된 위치로 이동*/}
void stop() {/*현재 위치에 정지*/}
void load() {/*선택된 대상 태움*/}
void unload() {/*선택된 대상 내림*/}
}
int x, y
, void move(int x, int y)
, void stop()
abstract
로 abstract class Unit{
int x, y; //현재 위치
abstract void move(int x, int y); /*지정된 위치로 이동*/
void stop() {/*현재 위치에 정지*/}
}
class Marine extends Unit{ //보병
void move(int x, int y) {
System.out.printf("보병 지정된 위치로 이동 : [%d, %d]%n", x, y);
}
void stimPack() {/*스팀팩을 사용*/}
}
class Tank extends Unit{ //탱크
void move(int x, int y) {
System.out.printf("탱크 지정된 위치로 이동 : [%d, %d]%n", x, y);
}
void changeMode() {/*공격모드를 변환*/}
}
class DropShip extends Unit{ //수송선
void move(int x, int y) {
System.out.printf("수송선 지정된 위치로 이동 : [%d, %d]%n", x, y);
}
void load() {/*선택된 대상 태움*/}
void unload() {/*선택된 대상 내림*/}
}
public class Ex7_10 {
public static void main(String[] args) {
Unit[] group = { new Marine(), new Tank(), new DropShip()};
/*
Unit[] group = new Unit[3];
group[0] = new Marine();
group[1] = new Tank();
group[2] = new DropShip(); 을 줄인 것!
*/
for(int i=0; i<group.length; i++) { //group[i].length 아니다!!
group[i].move(100, 200);
}
}
}
보병 지정된 위치로 이동 : [100, 200]
탱크 지정된 위치로 이동 : [100, 200]
수송선 지정된 위치로 이동 : [100, 200]
✨✨객체배열 : 참조변수 묶은 것
-> 객체배열 : group
??
-> 참조변수 : group[i]
✨group
의 타입은? : Unit[]
✨group[i]
의 타입은? : Unit
Unit
에 move()
가 있기에 abstract
여도 호출이 가능한 것
만약 Unit
대신 Object
를 썼다면?
-> Object
는 move()
가 없기에 호출이 불가능하다!