추상 클래스(abstract class)는 상속을 하기 위해 만드는 클래스이다.
즉 뼈대만 되는 클래스이고 절대 객체화 되어서는 안되는 클래스다. 이렇게 객체화 될 수 없게 하는 기능을
자바가 지원하는데, 바로 abstract이다.
abstract예약어를 선언하여 추상클래스를 선언할 수 있고, 추상메서드도 마찬가지이다.
Computer라는 추상 매서드, 그리고 이를 상속받는 Desktop, NoteBook, MyNoteBook 클래스를 생각해보자.
_________ Desktop
Computer ----(
------- NoteBook --------MyNoteBook
package abstractex;
public abstract class Computer { // 최상위 추상 클래스
public abstract void display(); // 추상 메서드1
public abstract void typing(); // 추상 메서드2
public void turnOn() { // 일반 메서드1
System.out.println("전원을 켭니다.");
}
public void turnOff() { // 일반 메서드2
System.out.println("전원을 끕니다.");
}
}
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()");
}
}
package abstractex;
public abstract class NoteBook extends Computer{
@Override // 상속받은 추상 메서드를 일반 메서드로 재정의.
public void display() {
System.out.println("NoteBook display()");
}
// 남은 추상메서드 하나를 구현하지 않았므로 얘는 추상 클래스이다.
}
package abstractex;
public class MyNoteBook extends NoteBook{
@Override // NoteBook의 추상 메서드를 일반 메서드로 정의.
public void typing() {
System.out.println("MyNoteBook typing()");
}
}
package abstractex;
public class ComputerTest {
public static void main(String[] args) {
에러발생 Computer c1 = new Computer(); //추상 클래스는 new불가.
Computer c2 = new DeskTop(); // 근데 추상 클래스로의 형 변환은 가능하다.
에러발생 Computer c3 = new NoteBook();
Computer c4 = new MyNoteBook();
}
}
추상 클래스는 모든 추상 메서드를 구현한 클래스이다. 추상 클래스만으로는 완벽한 기능이 구현된 것이 아니고, 공통 기능만을 구현해논다.
추상 클래스는 사용할 목적이 아닌 상속만을 위해 만든 클래스로, new 예약어로 인스턴스 생성이 불가능하다.
구현 메소드 : 하위 클래스에서 공통으로 사용할 구현 코드. 하위 클래스에서 재정의할 수도 있음.
추상 메소드: 하위 클래스가 어떤 클래스냐에 따라 구현 코드가 달라짐.
위의 컴퓨터 예시를 보면 turnOn()과 turnOff()의 구현은 하위 클래스에서 공유할 수 있지만, display()와 typing()의 구현은 NoteBook인지 Desktop인지에 따라 바뀌므로 따로 구현하지 않았다.
템플릿 메서드
템플릿 메서드란?
디자인 패턴의 하나로 추상클래스를 사용하여 구현할 수 있다. 메서드의 실행 순서와 시나리오를 결정해주는 역할을 한다.
추상메서드 Car와 이를 상속받은 AiCar, ManualCar클래스를 생각해보자.
package template;
public abstract class Car {
public abstract void drive();
public abstract void stop();
public abstract void wiper();
public void startCar() {
System.out.println("시동을 켭니다.");
}
public void turnOff() {
System.out.println("시동을 끕니다.");
}
final public void run() { // 이것이 템플릿 메소드. 메서드 실행순서와 시나리오를 정해준다.
// 요 템플릿 메서드는 바뀌면 안되기 때문에 final로 선언한다.
startCar();
drive();
stop();
wiper();
turnOff();
}
}
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("내가 조절");
}
}
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("비나 눈의 양에 따라 빠르기를 자동으로 조절");
}
}
package template;
public class CarTest {
public static void main(String[] args) {
System.out.println("=====자율주행======");
AICar myCar = new AICar();
myCar.run();
System.out.println("=====수동======");
Car hisCar = new ManualCar();
hisCar.run();
}
}
출력결과:
=====자율주행======
시동을 켭니다.
자율주행합니다.
자율주행으로 알아서 달립니다.
스스로 멈춥니다.
비나 눈의 양에 따라 빠르기를 자동으로 조절
시동을 끕니다.
=====수동======
시동을 켭니다.
내가 운전합니다.ㅠㅠ
내가 조작합니. ㅜㅡ
내가 브레이크 밟습니다. ㅜ
내가 조절
시동을 끕니다.
추상 클래스 Car를 정의하고 Ai인지 Manual인지에 따라사 추상 메서드를 일반 메서드로 재정의하였다.
최상위 클래스 Car에 final로 선언된 메소드가 템플릿 메소드이다.
템플릿 메소드는 어디에서도 수정할 수 없도록 final로 선언한다. 로직의 흐름을 결정하는 메서드이기 때문에 코드를 변경하면 안된다.
final 에약어
final변수는 상수를 의미한다.
final메서드는 하위클래스에서 재정의할 수 없다.
final클래스는 상속할 수 없다.
final은 상수를 의미하며 수정할 수 없다는 의미를 가진다. 상수를 선언할 때 에는 주로 대문자를 사용한다.
자바 프로젝트를 진행할 때 여러 파일에서 공유해야하는 산수 값은 한 파일에 모아 public static final로 선언하여 사용한다.
예시를 보고 마치자.
package finalex;
public class Define {
// 여러 파일에서 공유해야하는 상수 값은 public static final이다.
public static final int MIN = 1;
public static final int MAX = 99999;
public static final int ENG = 1001;
public static final int MATH = 2001;
public static final double PI = 3.14;
public static final String GOOD_MORNING = "goood mornig~~~";
}
'java' 카테고리의 다른 글
인터페이스 - 느슨한 결합력 (0) | 2021.04.25 |
---|---|
자바의 다형성 (0) | 2021.03.25 |
Java -3강 다형성, instanceof, 다운캐스팅 (0) | 2021.02.21 |
Java - 2강 상속, 묵시적 클래스 형 변환, 가상 메서드 (0) | 2021.02.21 |
Java-1강 상속 (0) | 2021.02.21 |