Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
Tags
- 자바의 정석 기초편 ch1
- jpa 활용2 - api 개발 고급
- 자바의 정석 기초편 ch6
- 자바의 정석 기초편 ch12
- @Aspect
- 자바의 정석 기초편 ch13
- 게시글 목록 api
- 스프링 mvc2 - 로그인 처리
- 스프링 mvc1 - 서블릿
- 스프링 mvc1 - 스프링 mvc
- 자바의 정석 기초편 ch8
- 자바의 정석 기초편 ch5
- 자바의 정석 기초편 ch7
- 자바의 정석 기초편 ch9
- 자바의 정석 기초편 ch11
- 2024 정보처리기사 수제비 실기
- 스프링 db1 - 스프링과 문제 해결
- 스프링 mvc2 - 타임리프
- 스프링 mvc2 - 검증
- 자바 중급1편 - 날짜와 시간
- 자바 기본편 - 다형성
- 자바의 정석 기초편 ch4
- 스프링 고급 - 스프링 aop
- 2024 정보처리기사 시나공 필기
- jpa - 객체지향 쿼리 언어
- 코드로 시작하는 자바 첫걸음
- 스프링 입문(무료)
- 스프링 db2 - 데이터 접근 기술
- 자바의 정석 기초편 ch2
- 자바의 정석 기초편 ch14
Archives
- Today
- Total
나구리의 개발공부기록
자바의 정석 기초편 ch7 - 31 ~ 34[추상 클래스, 추상 메서드, 추상클래스의작성1~2] 본문
유튜브 공부/JAVA의 정석 기초편(유튜브)
자바의 정석 기초편 ch7 - 31 ~ 34[추상 클래스, 추상 메서드, 추상클래스의작성1~2]
소소한나구리 2023. 11. 28. 17:321) 추상클래스
- 미완성 설계도(미완성 메서드를 갖고 있는 클래스)
- 미완성 메서드는 선언부만 가지고 있으며 구현부가 없음
- abstract 리턴타입 메서드이름(); 으로 정의함
- abstract를 붙힘으로 인하여 '나중에 완성해야 하는구나' 라는 인식을 주도록 할 수 있음 (필수 요소에 대한 강제성 부여)
- 클래스와 메서드 앞에 abstract 붙혀야 에러가 안남
- 다른 클래스 작성에 도움을 주기 위한 것으로 그 자체로는 인스턴스 생성이 불가능 함
- 상속을 통해 추상 메서드를 완성해야 인스턴스 생성 가능
// abstract를 안붙히면 에러남(메서드, 클래스 전부)
abstract class Player { // 추상클래스(미완성클래스)
abstract void play(int pos); // 추상메서드(블럭{}이 없는 미완성 메서드)
abstract void stop(); // 추상메서드
}
class AudioPlayer extends Player { // 추상클래스 상속
void play(int pos) { /* 내용생략 */ } // 추상메서드 구현
void stop() { /* 내용생략 */ } // 추상메서드 구현
}
public class Test {
public static void main(String[] args) {
// Player p = new Player(); // 에러, 추상클래스의 인스턴스 생성 불가
AudioPlayer ap = new AudioPlayer(); // 객체 생성 가능
Player p = new AudioPlayer(); // 조상 타입의 참조변수로도 가능(다형성)
}
}
- 메서드의 기능이 애플리케이션에 꼭 필요하지만 자손클래스마다 다르게 구현 될 것으로 예상되는 경우에 사용
- 추상클래스를 상속받고 추상 메서드를 전부 구현하지 않은채 abstract를 제외하면 에러 발생
- 즉, 상속받은 메서드의 일부만 구현하게되면 상속받은 클래스도 추상클래스가 됨
abstract class AbstractPlayer extends Player { // 일부만 구현한 추상클래스
// abstract를 붙히지 않으면 에러 발생!(미완성)
void play(int pos) { /* 내용생략 */ } // 상속받은 메서드 중 1개만 구현(미완성 메서드)
// abstract void stop(); 가 생략되어있음
}
- 메서드 호출할 때는 선언부만 필요하기 때문에 추상 메서드도 호출이 가능하긴 함
- 그러나 아무 기능이 없는 껍데기 이므로 보통은 상속을 통해 자손이 메서드를 완성시키고 객체생성 후 저장한 참조변수로 추상메서드 호출하여 정의한 기능을 수행하는 방식으로 사용함 -> 실무에서 자주 사용하는 인터페이스를 이런식으로 주로 사용하게됨
abstract class Player { // 추상클래스
boolean pause;
int currentPos;
Player() { // 추상클래스의 생성자
pause = flase;
currentPos = 0;
}
// abstract를 써줌으로 인해 자손을 통해 메서드를 완성 시켜야 한다는 내용을 공유
abstract void play(int pos); // 추상메서드 -> 필수기능
abstract void stop(); // 추상메서드 -> 필수기능
void play() { // 추상클래스의 인스턴스 메서드
play(currentPos); // 추상메서드 호출
}
}
(1) 예제
- 일반적으로 추상메서드를 사용하는 예제
- 추상 클래스인 Player를 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 ex_7_PlayerTest {
public static void main(String[] args) {
// Player p = new Player(); //추상 클래스의 객체를 그냥 생성 -> 에러!
AudioPlayer ap = new AudioPlayer(); // 객체 생성
// 자손객체에서 정의한 추상 메서드를 호출하여 사용
ap.play(100);
ap.stop();
Player p = new AudioPlayer(); // 다형성(조상의 객체로 변경 생성 - 가능)
p.play(100);
p.stop();
}
}
2) 추상클래스의 작성
- 여러 클래스에 공통적으로 사용될 수 있는 추상클래스를 바로 작성하거나, 기존클래스의 공통 부분을 뽑아서 추상클래스를 작성함
- 비즈니스 로직상에서 Unit이라는 큰 카테고리의 추상 클래스를 만들어서 각 Unit의 하위분류인 Marine, Tank, Dropship의 클래스를 Unit을 구현하게 되면 공통 속성의 메서드를 중복해서 작성해야하는 번거로움을 줄일 수 있음
- Unit에 있는 추상메서드 move덕분에 객체 배열에담겨있는 객체들마다 정의가 다르게 되어있는 move 메서드를 동시에 호출이 가능함
(1) 예제
- 이미지의 예제를 실제 구현한 예제
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].move(100, 200);
// group의 타입 = unit[]
// group[0] ~ [2]의 타입 = unit
// 반목문을 풀어 쓰면?
// group[0].move(100,200) // Marine 객체의 move(100,200)을 호출
// group[1].move(100,200) // Tank 객체를 위와 같이 호출
// group[2].move(100,200) // Dropship 객체를 위와 같이 호출
// 만일 unit[]이 아닌 object[]로 바꾼다면? -> 에러발생
// object클래스(최고조상 클래스)에는 move멤버가 없음 (unit클래스에 move가 있음)
// object[] group = { new Marine(), new Tank(), new Dropship() };
}
}
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() { /* 선택된 대상을 내린다. */ }
}
(2) 추상클래스의 장점
- 코드 중복을 제거하고 작성을 쉽게 하고 관리(변경)가 용이해짐
- 추상클래스를 의미있는 단계별로 생성해놓으면 중간단계의 클래스를 상속받아서 새로운 클래스를 구현이 가능
- 추상화된 코드는 구체화된 코드보단 유연하여 변경에 유리(유지보수가 용이함)
- 구체적 코드처럼 new로 객체를 생성해 버리면 메서드를 수정할 때마다 해당 메서드가 사용 된 모든 곳을 바꿔 줘야함
- 추상적 코드처럼 상속하여 사용할 경우 createCalendar메서드만 수정하면 호출 된 모든 곳에 반영 -> 변경에 유리
** 출처 : 남궁성의 정석코딩_자바의정석_기초편 유튜브 강의
'유튜브 공부 > JAVA의 정석 기초편(유튜브)' 카테고리의 다른 글
자바의 정석 기초편 ch7 - 39 ~ 41[인터페이스의 장점, 인터페이스의 디폴트메서드] (0) | 2023.11.29 |
---|---|
자바의 정석 기초편 ch7 - 35 ~ 38 [인터페이스의 선언, 상속, 구현, 인터페이스와 다형성] (0) | 2023.11.29 |
자바의 정석 기초편 ch7 - 27 ~ 30[매개변수다형성,여러종류의 객체를 배열로 다루기] (0) | 2023.11.27 |
자바의 정석 기초편 ch7 - 24 ~ 26[참조변수의형변환,instanceof 연산자] (1) | 2023.11.27 |
자바의 정석 기초편 ch7 - 22 ~ 23 [캡슐화, 다형성] (1) | 2023.11.24 |