Chap 09. 추상 클래스 [Do it! 자바 프로그래밍 입문]

doriskim·2022년 12월 13일
0

*본 내용은 [Do it! 자바 프로그래밍 입문] 책과 강의를 보고 공부하면서 요점 정리한 내용입니다.

◼ 추상 클래스(abstract class)

✔ 추상 클래스란?

  • 추상 메서드를 포함한 클래스
    (추상 메서드를 포함하고 있지 않다고 해도 추상 클래스가 될 수는 있다.)

  • 추상 메서드는 구현코드없이 메서드의 선언만 있다.

public abstract void display(); // 추상 메서드 - 구현을 안하고 메서드를 선언만 하겠다는 의미
public void display() {} // 추상 메서드가 아니다. {}에 아무것도 작성하지 않아도 구현부가 있는 것으로 본다.
  • abstract 예약어를 사용한다. abstract로 선언된 메서드를 가진 클래스는 abstract로 선언 한다. 만약 모든 메서드가 구현코드가 있지만 클래스가 abstract로 선언된 경우 추상 클래스가 되고 new 할 수 없다.

  • 추상 클래스는 new(인스턴스 화) 할 수 없다.

  • cf) concrete class 구현 클래스

  • 추상 클래스는 상속을 위한 클래스이다.

  • 추상 메서드는 하위 클래스가 구현해야만 하는 메서드이다.
    하위 클래스에서 구체적으로 구현할 필요가 있을 때 상위 클래스에서 추상 메서드로 둔다.

  • 구현된 메서드: 하위 클래스가 공통으로 사용할 수 있는 기능을 구현한다.
    경우에 따라서는 하위 클래스가 재정의(overriding)할 수 있다.

✔ 추상 클래스 구현하기

Computer.java

package abstractex;

public abstract class Computer { 

	//추상 메서드
	public abstract void display();
	public abstract void typing();

	//구현된 메서드 - 추상 클래스에서 일반 메서드도 구현 가능하다.
	public void turnOn() {
		System.out.println("전원을 켭니다.");
	}
	
	public void turnOff() {
		System.out.println("전원을 끕니다.");
	}
}

DeskTop.java

package abstractex;

public class DeskTop extends Computer{
	
	@Override
	public void display() {
		System.out.println("DeskTop display()");
	}
	
	@Override
	public void typing() {
		System.out.println("DeskTop typing()");
	}

}

NoteBook.java

package abstractex;

public abstract class NoteBook extends Computer {

	@Override
	public void display() {
		System.out.println("NoteBook display()");
	}

}

ComputerTest.java

package abstractex;

public class ComputerTest {

	public static void main(String[] args) {
		
//		Computer c1 = new Computer(); // 오류 발생, 추상클래스는 인스턴스화 불가능
		Computer c2 = new DeskTop(); // 가능
//		Computer c3 = new NoteBook(); // 불가능
		Computer c4 = new MyNoteBook(); // 가능
		NoteBook c5 = new MyNoteBook(); // 가능

		c2.display();
		c4.display();
	}

}

실행 결과

DeskTop display()
NoteBook display()

◼ 추상 클래스와 템플릿 메서드

✔ final 예약어

  • final 변수
	public static final double PI = 3.14;

∙ final 변수는 값이 변경될 수 없는 상수이다.
∙ 프로젝트 구현시 여러 파일에서 공유해야 하는 상수 값은 하나의 파일에 선언하여 사용하면 편리하다.
∙ final 변수는 오직 한 번만 값을 할당할 수 있다.

  • final 메서드는 하위 클래스에서 재정의(overriding)할 수 없다.

  • final 클래스는 더 이상 상속되지 않는다.
    예) java의 String 클래스

✔ 템플릿 메서드

	// 두가지 형태 모두 가능
	public final void run() {}
	final public void run() {} 
  • 템플릿 메서드: 추상 메서드나 구현된 메서드를 활용하여 전체 기능의 흐름(시나리오)을 정의하는 메서드
  • final로 선언하면 하위 클래스에서 재정의 할 수 없다.
  • 프레임 워크에서 많이 사용되는 설계 패턴이다.
  • 추상 클래스로 선언된 상위 클래스에 템플릿 메서드를 활용하여 전체적인 흐름을 정의하고 하위 클래스에서 다르게 구현되어야 하는 부분은 추상 메서드로 선언해서 하위 클래스가 구현하도록 한다.

Car.java

package template;

public abstract class Car {

	public abstract void drive();
	public abstract void stop();
	public abstract void wiper();
	
	public void washCar() {} // 훅메서드 - 필요에 의해 재정의 해서 쓸 수 있음
	
	public void startCar() {
		System.out.println("시동을 켭니다.");
	}
	
	public void turnOff() {
		System.out.println("시동을 끕니다.");
	}
	
	//템플릿 메서드
	public final void run() {
		startCar();
		drive();
		wiper();
		stop();
		washCar(); // 훅메서드
		turnOff();
	}
}

ManualCar.java

package template;

public class ManualCar extends Car{

	@Override
	public void drive() {
		System.out.println("사람이 운전합니다.");
		System.out.println("사람이 핸들을 조작합니다.");
	}

	@Override
	public void stop() {
		System.out.println("사람이 브레이크로 정지합니다.");
	}

	@Override
	public void wiper() {
		System.out.println("사람이 수동으로 와이퍼를 조작합니다.");
	}

//	public void run() {} // 템플릿 메서드이므로 재정의 하려고 하면 오류 남
}

AICar.java

package template;

public class AICar extends Car{

	@Override
	public void drive() {
		System.out.println("자율 주행합니다.");
		System.out.println("자동차가 스스로 방향을 전환합니다.");
	}

	@Override
	public void stop() {
		System.out.println("자동차가 스스로 멈춥니다.");
	}

	@Override
	public void wiper() {
		System.out.println("비나 눈의 양에 따라 자동으로 조절됩니다.");
	}
	
	@Override
	public void washCar() {
		System.out.println("자동으로 세차가 됩니다.");
	}

}

CarTest.java

package template;

public class CarTest {

	public static void main(String[] args) {
		
		Car myCar = new ManualCar();
		myCar.run();
		
		System.out.println("==============");
		
		Car yourCar = new AICar();
		yourCar.run();
	}

}

실행 결과

시동을 켭니다.
사람이 운전합니다.
사람이 핸들을 조작합니다.
사람이 수동으로 와이퍼를 조작합니다.
사람이 브레이크로 정지합니다.
시동을 끕니다.
==============
시동을 켭니다.
자율 주행합니다.
자동차가 스스로 방향을 전환합니다.
비나 눈의 양에 따라 자동으로 조절됩니다.
자동차가 스스로 멈춥니다.
자동으로 세차가 됩니다.
시동을 끕니다.

✔ 템플릿 메서드 구현 예


(※ 추상 클래스, 추상 메서드는 이태리체로 표현한다.)

  • 각 PlayerLevel 별 가능한 기능이 다르다.
    단, 기능의 순서는 run(), jump(), turn()의 순서이다.

  • 기능의 순서와 반복에 대한 구현은 go(int) 메서드에서 구현되어 있다.(템플릿 메서드)

  • 각 레벨마다 run(), jump(), turn() 기능은 다르게 구현되어야 하므로 추상 메서드로 선언한다.

MainBoard.java

package gamelevel;

public class MainBoard {
	
	public static void main(String[] args) {
		
		Player player = new Player();
		player.play(1); // 1번 점프
		
		AdvancedLevel aLevel = new AdvancedLevel();
		player.upgradeLevel(aLevel);
		player.play(2); // 2번 점프
		
		SuperLevel sLevel = new SuperLevel();
		player.upgradeLevel(sLevel);
		player.play(3); // 3번 점프
		
	}

}

Player.java

package gamelevel;

public class Player {

	private PlayerLevel level;

	public Player() {
		level = new BeginnerLevel();
		level.showLevelMessage();
	}
	
	public PlayerLevel getLevel() {
		return level;
	}

	public void upgradeLevel(PlayerLevel level) {
		this.level = level;
		level.showLevelMessage();
	}
	
	public void play(int count) {
		level.go(count);
	}
	
	
}

PlayerLevel.java

package gamelevel;

public abstract class PlayerLevel {
	
	public abstract void run();
	public abstract void jump();
	public abstract void turn();
	public abstract void showLevelMessage();
	
	final public void go(int count) {
		run();
		for(int i = 0 ; i < count ; i++) {
			jump();
		}
		turn();
	}

}

BeginnerLevel.java

package gamelevel;

public class BeginnerLevel extends PlayerLevel {

	@Override
	public void run() {
		System.out.println("천천히 달립니다.");
	}

	@Override
	public void jump() {
		System.out.println("jump 할 줄 모르지롱~");
	}

	@Override
	public void turn() {
		System.out.println("turn 할 줄 모르지롱~");
	}

	@Override
	public void showLevelMessage() {
		System.out.println("*****초보자 레벨입니다*****");
	}

}

AdvancedLevel.java

package gamelevel;

public class AdvancedLevel extends PlayerLevel{

	@Override
	public void run() {
		System.out.println("빨리 달립니다.");
	}

	@Override
	public void jump() {
		System.out.println("높이 jump 합니다.");
	}

	@Override
	public void turn() {
		System.out.println("turn 할 줄 모르지롱~");
	}

	@Override
	public void showLevelMessage() {
		System.out.println("*****중급자 레벨입니다*****");
	}

}

SuperLevel.java

package gamelevel;

public class SuperLevel extends PlayerLevel {
	
	@Override
	public void run() {
		System.out.println("겁나게 빨리 달립니다.");
	}

	@Override
	public void jump() {
		System.out.println("겁나게 높이 jump 합니다.");
	}

	@Override
	public void turn() {
		System.out.println("한 바퀴 돕니다.");
	}

	@Override
	public void showLevelMessage() {
		System.out.println("*****고급 레벨입니다*****");
	}


}

실행 결과

*****초보자 레벨입니다*****
천천히 달립니다.
jump 할 줄 모르지롱~
turn 할 줄 모르지롱~
*****중급자 레벨입니다*****
빨리 달립니다.
높이 jump 합니다.
높이 jump 합니다.
turn 할 줄 모르지롱~
*****고급 레벨입니다*****
겁나게 빨리 달립니다.
겁나게 높이 jump 합니다.
겁나게 높이 jump 합니다.
겁나게 높이 jump 합니다.
한 바퀴 돕니다.

0개의 댓글

관련 채용 정보