자바(9) - 추상클래스
2021년08월05일추상 클래스
추상적이다의 의미는 구체적이지 않고 막연한 것을 뜻한다. 추상 클래스 또한 구체적이지 않은 클래스라고 보면 된다. 추상 클래스를 영어로는 abstract class라고 하고 추상 클래스가 아닌 클래스는 concrete class라고 한다. 이전까지 썼던 클래스들은 전부 concrete 클래스였던 것이다. 추상 클래스는 항상 추상 메서드를 포함한다. 추상 메서드는 구현 코드가 없다. 즉 몸체가 없다는 뜻이다. {}로 감싼 부분을 함수의 구현부(implementation)라고 하는데 이 부분이 없다는 것이다. 추상 메서드는 아래와 같이 선언한다. 참고로 추상 메서드는 new예약어로 인스턴스를 생성할 수 없다.
abstract int add(int x, int y);
선언은 일반 함수랑 비슷해 보이지만 앞에 abstract이라는 예약어가 붙고 중괄호 대신 끝에 세미 콜론으로 마무리 된다. 추상 클래스를 한 번 구현해보자. 먼저 컴퓨터라는 클래스를 만들어 보겠다. 컴퓨터에서 파생되는 종류로는 데스크탑과 노트북이 있다. 컴퓨터의 기능으로는 display, typing이 있고 전원 켜기, 끄기 같은 기능이 있다. 켜기 끄기는 데탑, 노트북의 공통 기능들이니 추상 클래스에서 구현해보도록 한다.
public abstract class Computer {
public abstract void display();
public abstract void typing();
public void turnOn() {
System.out.println("전원을 켭니다.");
}
public void turnOff() {
System.out.println("전원을 끕니다.");
}
}
public class DeskTop extends Computer {
@Override
public void display() {
}
@Override
public void typing() {
}
}
public abstract class NoteBook extends Computer {
@Override
public void display() {
System.out.println("NoteBook display()");
}
}
public class MyNoteBook extends NoteBook {
@Override
public void typing() {
System.out.println("MyNoteBook typing()");
}
}
추상 클래스 컴퓨터를 상속받은 데스크탑은 반드시 추상메서드를 오버라이딩해서 구현해주어야 한다. 만약 상속받은 클래스에서 추상 메서드들에 대해 전부 구현하지 않으면 그 클래스 또한 추상 클래스로 선언해주어야 하고, 최종적이 클래스에서 남은 추상메서드들을 다 구현해주어야 한다.
템플릿 메서드
템플릿이란 틀이나 견본을 뜻한다. 템플릿 메서드는 틀이 있는 메서드라는 의미이다. 템플릿 메서드는 디자인 패턴의 한 방법으로 모든 객체 지향 프로그램에서 사용하는 구현 방법이다. 아래는 예제이다.
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();
}
}
2개의 추상 메서드와 3개의 구현 메서드가 있다. 시동 on/off메서드는 자동차의 공통 부분이라 추상메서드에서 구현한 것이다. run()메서드는 자동차가 달리는 방법을 순서대로 구현해 둔 것이다. Car 클래스를 상속받으면 어떤 자동차든 모두 이 순서대로 실행된다. 우리는 아래 상속받은 클래스처럼 추상 메서드 부분만 구현해주면 된다.
public class AICar extends Car {
@Override
public void drive() {
System.out.println("AI 운전");
System.out.println("AI 핸들 조작");
}
@Override
public void stop() {
System.out.println("AI 정지");
}
}
public class ManualCar extends Car {
@Override
public void drive() {
System.out.println("사람이 운전");
System.out.println("사람이 핸들 조작");
}
@Override
public void stop() {
System.out.println("브레이크로 정지");
}
}
public class CarTest {
public static void main(String[] args) {
Car myCar = new AICar();
myCar.run();
Car hisCar = new ManualCar();
hisCar.run();
}
}
테스트 부분을 보면 인스턴스들을 만들고 run을 했다. 자동차의 작동 순서는 AI나 수동이나 동일하다. 시동을 키고, 주행하고, 멈추고 시동을 끈다. 그렇기에 템플릿 메서드를 활용하여 메서드 실행 순서와 시나리오를 정의하는 것이다. 이 내용을 하위 클래스에서 재정의 하면 안되기에 final 예약어를 사용하여 재정의 할 수 없게 만든다.
final 예약어
final을 사용하면 더 이상 수정할 수 없음을 의미하는 것이다. |사용위치|설명| |—–|—| |변수|상수를 의미| |메서드|하위 클래스에서 재정의할 수 없음| |클래스|상속할 수 없음|