📌 학습 목차
33-1. 추상 클래스의 작성 예제1
33-2. 추상 클래스의 작성 예제2
33-1. 추상 클래스의 작성 예제1
•추상 클래스는 상속을 통해 자손 클래스에서 추상 메서드를 오버라이딩으로 모두 구현함
이때 추상 메서드 중 하나라도 구현하지 않을 경우, 자손 클래스 또한 추상 클래스로 지정해야 함
// 추상 클래스로 정의하지 않은 경우
class Footballer {
int x, y; // 지정 위치
void move(int x, int y) { /* 지정 위치로 이동 */ }
void stop() { /* 지정 위치에 정지 */ }
void run() { /* 달리기 시작 */ }
void kick() { /* 공차기 시작 */ }
}
class Skater {
int x, y; // 지정 위치
void move(int x, int y) { /* 지정 위치로 이동 */ }
void stop() { /* 지정 위치에 정지 */ }
void jump() { /* 점프 시도 */ }
void spin() { /* 스핀 시도 */ }
}
// 공통 부분을 뽑아 추상 클래스를 정의한 경우
📌 // 1) 추상 클래스 정의
abstract class Player {
int x, y;
Player2() {
x = 0;
y = 0;
}
abstract void move(int x, int y);
abstract void stop();
}
📌 // 2-1) 추상 메서드를 모두 구현한 자손 클래스
class Footballer extends Player {
@Override
void move(int x, int y) { /* 내용 생략 */ }
@Override
void stop() { /* 내용 생략 */ }
void run() { /* 내용 생략 */ }
void kick() { /* 내용 생략 */ }
}
📌 // 2-2) 추상 메서드를 일부만 구현한 자손 클래스
abstract class Skater extends Player {
@Override
void move(int x, int y) { /* 내용 생략 */ }
void jump() { /* 내용 생략 */ }
void spin() { /* 내용 생략 */ }
}
1) 추상 클래스 정의
•기존 클래스에서 공통적으로 사용되는 부분을 뽑아 추상 클래스인 Player 클래스를 정의함
•모든 선수는 경기가 시작되는 특정 위치로 이동해 정지해야 하나 종목에 따라 메서드 구현 내용이 달라질 수 있으므로
move와 stop 메서드를 추상 메서드로 정의함
2-1) 추상 메서드를 모두 구현한 자손 클래스
•Player 클래스를 상속받은 Footballer 클래스에서 추상 메서드 move와 stop을 오버라이딩으로 모두 구현함
2-2) 추상 메서드를 일부만 구현한 자손 클래스
•Player 클래스를 상속받은 Footballer 클래스에서 추상 메서드 중 move 메서드만 구현함에 따라,
클래스 선언부에 abstract 제어자를 사용하여 추상 메서드 구현이 필요한 추상 클래스임을 나타냄
33-2. 추상 클래스의 작성 예제2
•기존 클래스에서 공통적으로 사용되는 부분을 뽑아 작성한 추상 클래스는 이를 상속받는 자손 클래스 간의 공통 조상에 해당함
•다형성에 의해 조상 타입의 참조 변수로 자손 타입의 객체를 참조하는 것이 가능하므로,
공통 조상인 추상 클래스 타입의 참조 변수 배열에 여러 종류의 자손 타입 객체를 담아 하나의 묶음으로 간단히 다룰 수 있음
•추상 클래스 타입의 참조 변수로 추상 메서드를 호출할 경우,
추상 클래스에 정의된 추상 메서드가 아닌 추상 메서드가 구현된 객체의 메서드가 호출됨
•모든 클래스의 최고 조상인 Object 클래스 타입의 참조 변수 배열 또한 여러 종류의 객체를 담아 하나의 묶음으로 간단히 다룰 수 있으나,
Object 클래스에 정의되지 않은 멤버를 호출할 경우 에러가 발생함
package chap_07;
// 1) 추상 클래스
abstract class Player2 {
int x, y;
Player2() {
x = 0;
y = 0;
}
abstract void move(int x, int y);
abstract void stop();
}
// 2-1) 자손 클래스
class Footballer2 extends Player2 {
@Override
void move(int x, int y) { System.out.println("Footballer2: (" + x + ", " + y + ")로 이동"); }
@Override
void stop() { /* 내용 생략 */ }
void run() { /* 내용 생략 */ }
void kick() { /* 내용 생략 */ }
}
// 2-2) 자손 클래스
class Skater1 extends Player2 {
@Override
void move(int x, int y) { System.out.println("Skater1: (" + x + ", " + y + ")로 이동"); }
@Override
void stop() { /* 내용 생략 */ }
void jump() { /* 내용 생략 */ }
void spin() { /* 내용 생략 */ }
}
public class _33_Example {
public static void main(String[] args) {
📌 // 3-1) 추상 클래스 타입의 참조 변수 배열 생성 및 메서드 호출
Player2[] g1 = { new Footballer2(), new Skater1() };
for (int i = 0; i < g1.length; i++) {
g1[i].move(100, 200);
}
/*
Footballer2: (100, 200)로 이동
Skater1: (100, 200)로 이동
*/
📌 // 3-2) Object 클래스 타입의 참조 변수 배열 생성 및 메서드 호출
Object[] g2 = { new Footballer2(), new Skater1() };
// for (int i = 0; i < g2.length; i++) {
// g2[i].move(100, 200); -> 에러 발생
// }
}
}

3-1) 추상 클래스 타입의 참조 변수 배열 생성 및 메서드 호출
•공통 조상인 Player 타입의참조 변수 배열을 생성해 Footballer 인스턴스와 Skater 인스턴스를 담아 하나의 묶음으로 다룰 수 있게됨
•Player 타입의 참조 변수 g1으로 'g1[i].move(100, 200)'와 같이 추상 메서드 move를 호출할 경우,
Player 클래스에 정의된 추상 메서드 move가 아닌
추상 메서드가 구현된 Footballer 인스턴스와 Skater 인스턴스의 move 메서드가 호출됨
3-2) Object 클래스 타입의 참조 변수 배열 생성 및 메서드 호출
•모든 클래스의 최고 조상인 Object 클래스 타입의 참조 변수 배열을 생성할 경우,
3-1)과 같이 Footballer 인스턴스와 Skater 인스턴스를 담아 하나의 묶음으로 다룰 수 있으나,
'g2[i].move(100, 200)'와 같이 Object 클래스에 정의되지 않은 move 메서드를 호출함에 따라 에러가 발생함
Reference
[남궁성의 정석코딩] Java의 정석 기초편 강의
[도우출판] Java의 정석 기초편 / 기본편