추상 클래스란, 완전하지 않은 클래스를 의미한다. 완전하지 않다는 것은 추상 클래스가 포함하는 메서드의 구현이 완전하지 않다는 것을 의미한다. 따라서 추상 클래스는 항상 추상 메서드를 포함하고, 추상 메서드는 구현부 대신 ;
를 사용한다. 추상 메서드와 클래스는 abstract
예약어를 사용한다.
public abstract class Computer {
public abstract void display();
public abstract void typing();
public void turnOn () {
System.out.println("전원을 켭니다");
}
public void turnOff () {
System.out.println("전원을 끕니다");
}
}
위 코드에서 display
와 typing
메서드는 Computer
를 상속받는 하위 클래스에 따라 다르게 구현될 수 있다. 그러나 turnOn
과 turnOff
는 공통인 코드이다.
Computer를 상속받는 Desktop클래스를 작성하자
public class DeskTop extends Computer {
@Override
public void display () {
System.out.println("DeskTop Display");
}
@Override
public void typing () {
System.out.println("DeskTop typing");
}
}
DeskTop클래스는 추상 메서드를 모두 구현했으므로 abstract예약어를 사용하지 않는다. 만약 추상 메서드 중 일부만 구현했다면 abstract를 사용한 추상 클래스여야 한다.
추상클래스는 상속을 하기 위해 만든 클래스이다. 상위클래스에서 공통으로 사용하는 코드를 작성하고 하위 클래스에서는 각자가 사용할 코드를 구현한다. 물론 상위 클래스에서 구현한 메서드를 하위 클래스에서 재정의(오버라이딩)할 수도 있다.
템플릿 메서드는 디자인패턴 중 하나로, 틀이 정해진 메서드를 의미한다. 템플릿 메서드를 사용하면 실행의 순서를 정할 수 있다. 템플릿 메서드를 사용하면 실행의 순서는 정해놓고 구현은 상속받는 각 하위 클래스마다 다르게 할 수 있게된다.
예를들어 Car
라는 클래스에서 run()
이라는 템플릿 메서드를 작성해보자. 차가 동작한다는 것은
- 차의 시동을 켠다
- 운전을 한다
- 브레이크를 밟아 차가 멈춘다
- 차의 시동을 끈다
의 순서로 이루어져있다. 이것을 템플릿 메서드를 사용하여 코드로 구현하면 다음과 같다.
public abstract class Car {
public abstract void drive();
public abstract void stop();
//시동을 켜고 끄는 것은 모든 차가 동일하므로 미리 구현
public void startCar() {
System.out.println("시동을 켭니다");
}
public void turnOff() {
System.out.println("시동을 끕니다");
}
final public void run() { //템플릿 메서드
startCar();
drive();
stop();
turnOff();
} //이렇게 순서를 정해놓음
}
Car
클래스를 상속받는 두가지의 클래스를 만들자. 하나는 자율주행이 가능한 AICar
이고 하나는 일반적인 ManualCar
이다.
public class AICar extends Car {
@Override
public void drive() {
System.out.println("자율주행합니다.");
}
public void stop() {
System.out.println("스스로 멈춥니다.");
}
}
public class ManualCar extends Car {
@Override
public void drive() {
System.out.println("사람이 운전합니다.");
}
public void stop() {
System.out.println("브레이크로 멈춥니다.");
}
}
이후 메인함수를 실행해 테스트해보면 AICar.run()
은
시동을 켭니다
자율 주행합니다
스스로 멈춥니다
시동을 끕니다
ManualCar.run()
은
시동을 켭니다
사람이 운전합니다
브레이크로 정지합니다
시동을 끕니다
로 출력이 된다. 공통부분인 startCar
와 turnOff
는 동일하게 출력되고 각각 구현한 drive
와 stop
은 각자의 특성에 맞게 출력되었다. 그러나 전체적인 동작의 순서는 같다. 따라서 이렇게 변하지 않는 순서, 로직의 흐름을 템플릿 메서드로 정의하는 것이다.
템플릿 메서드는 실행의 흐름을 정의하는 메서드이므로 하위 클래스에서 이 로직을 함부로 변경해서는 안된다. 따라서 final
예약어를 사용해 수정이 되지 않도록 하는 것이다.