7-33 추상 클래스의 작성 1
- 여러 클래스에 공통적으로 사용될 수 있는 추상 클래스를 바로 작성하거나
기존 클래스의 공통부분을 뽑아서 추상 클래스를 만든다.
move메서드가 선언부는 같지만 실제 내용(몸통)은 다를 것이다. 불일치
void move(int x, int y)는 같지만
{} 몸통은 클래스마다 다르다.
공통부분을 추출해서 Unit 클래스로 정의했다.
(공통부분을 뽑는다고 꼭 추상 클래스는 아님)
그래서 코드의 중복이 제거됐다.
Unit 클래스의 move()를 abstract 안 붙이고 몸통{}만 만들어 줄 수 있다.
그러면 자손들이 move() 메서드가 구현되었다고 생각해서 구현 안 할 수도 있다.
사용하는 사람들도 Unit 클래스가 추상 클래스가 아니니까 써도 되겠다고 생각할 수 있다.
Unit u = new Unit();
u.move();
꿈쩍도 안 한다. 그런 일이 벌어져서는 안 된다.
그래서 조상이 Unit는 추상클래스로 놔두고
이걸 자손들이 구현을 하는 것이다.

group[i].move(100, 200); 호출하면
abstract void move(int x, int y) 호출 x
실제 객체의 move()가 호출된다.
예
group[0].move(100, 200);
Marine 클래스의 move() 메서드가 실행된다.
리모컨이 추상 메서드라고 해도 실제 호출되는 건
인스턴스에 구현된 메서드가 호출된다.
Unit 클래스에 move() 메서드가 있기 때문이다.
Unit 리모콘에 move() 버튼이 있는 것이다.
만약에 추상 메서드라도 메서드들이 각자 다르니까
move() 메서드가 없다고 가정해보자.
그럼 group[i].move(100, 200); 코드를 쓸 수 없다.
for(int i=0;i< group.length;i++) { < 배열 안에 있는 탱크, 병사 , 수송선 등을
group[i].move(100, 200); 한 번에 움직이는 것이다.
}
다형성으로 하나의 배열에 여러 객체를 집어넣는다.
그래서 여러 종류의 유닛을 배열에 담아서 한번에 이동시킬 수 있다.
그런데 이동시키려고 하면 이동시키는 방법이 메서드마다 각자 다르다.
공중 유닛과 지상 유닛은 움직이는 게 다르니까
원래는 각자의 메서드를 호출해서 이동시켜야 하는데
그렇게 하려면 Unit 리모컨에 단추가 있어야 한다.
그럴려니까 추상 메서드로라도 move가 포함되어 있어야 한다.

만약 Object 배열에 담았다고 생각해보자.
Object는 최고 조상이니까 하나의 배열에 여러 객체가 저장될 수 있다.
그런데 group[i].move(100, 200);를 호출할 수 없다.
Object 클래스에는 move라는 단추가 없기 때문이다.
그래서 에러가 난다.
Unit[]에서 group[i]이라는 배열의 리모컨에는 뭐가 있나?
move()가 있다.
int와 int[]는 다른 타입이다.
int는 기본형
int[] 배열은 참조형
group의 타입은 Unit[]이다.(유닛 배열)
Unit[]배열에다가 Unit들을 넣은 것이다.
group[i]의 타입은 Unit이다.
group이라는 배열에 담긴 객체들에 move를 반복적으로 호출하는 것이다.
그래서 Marine, Tank, Dropship을 한 번에 이동시키는 것이다.
근데 각 객체가 이동하는 방법이 다르니까 배열에 넣어놓고
각 객체에 move를 호출하는 것이다.
여기서 호출하는 move()는 추상메서드가 아닌 실제 구현된 메서드 move()다.

객체배열 = 참조변수 묶은 것

Unit 리모콘에 move 단추를 만드려고
없으면 move를 호출하는 게 안되니까
group[0].move(100, 200); < 이런 식으로
public class Su2_5 {
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].move(100, 200);
}
}
}
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.println("Marine[x=" + x + ",y=" + y + "]");
}
void stimPack() { /* 스팀팩을 사용한다. */ }
}
class Tank extends Unit { // 탱크
void move(int x, int y) {
System.out.println("Tank[x=" + x + ",y=" + y + "]");
}
void changeMode() { /* 공격모드를 사용한다. */ }
}
class Dropship extends Unit {
void move(int x, int y) {
System.out.println("Dropship[x=" + x + ",y=" + y + "]");
}
void load() { /* 선택된 대상을 태운다. */ }
void unload() { /* 선택된 대상을 내린다. */ }
}
실습을 수십 번씩 쳐봐야 한다.
'프로그래밍 언어 > 자바의 정석 기초편' 카테고리의 다른 글
자바의 정석 기초편 ch7-35~37 인터페이스의 선언, 상속, 구현 (0) | 2022.10.24 |
---|---|
자바의 정석 기초편 ch7-33,34 추상클래스의작성2 (0) | 2022.10.24 |
자바의 정석 기초편 ch7-31,32 추상 클래스, 추상 메서드 (1) | 2022.09.30 |
자바의 정석 기초편 ch7-29,30 여러 종류의 객체를 배열로 다루기 (0) | 2022.09.16 |
자바의 정석 기초편 ch7-27,28 매개변수 다형성 (0) | 2022.09.05 |