추상 클래스 && 템플릿 메서드 && final 예약어

박정훈·2021년 1월 22일
0

java

목록 보기
11/15

추상 클래스(abstract class)

추상적이라는 것은 구체적이지 않고 막연한 것을 뜻한다.
추상 클래스는 메서드 오버라이딩을 강제하기 위해서 사용한다.
추상 클래스가 아닌 클래스를 concrete class 라고 한다. 일반적으로 그냥 클래스라고 한다.

추상 클래스는 항상 추상 메서드를 포함한다. 추상 메서드는 구현 코드가 없다. 함수의 구현 코드가 없다는 것은 함수 몸체가 없다는 뜻이다.

int add(int x, int y){
	return (x + y);
}

중괄호로 감싼 부분을 함수의 구현부(implementation)라고 한다. 이 부분이 없는 함수는 추상 함수(abstract function)이고 자바에서는 추상 메서드(abstract method)라고 한다. 추상 메서드는 다음과 같이 선언만 하며 abstract 예약어를 사용한다. 그리고 {}대신 ;를 쓴다.

abstract int add(int x, int y);

다음과 같은 메서드는 추상 메서드가 아닌다. {}를 사용한 것만으로도 메서드를 구현한 셈이다. 다만 {}안에 코드가 없어서 해당 메서드는 아무런 기능을 하지 않을 뿐이다.

int add(int x, int y){}

자바에서 추상 메서드는 abstract 예약어를 사용하여 선언만 하는 메서드이다.

  • 함수의 선언부
    함수의 선언부(declaration) 즉 반환 값, 함수 이름, 매개변수를 정의한다는 것은 곧 함ㅅ수의 역할이 무엇인지 어떻게 구현해야 하는지를 정의한다는 뜻이다. 따라서 함수 몸체를 구현하는 것보다 중요한 것은 함수 선언부를 작성하는 것이다. 메서드를 선언한다는 것은 메서드가 해야 할 일을 명시해 두는 것이다.
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 클래스가 Computer 클래스를 상속받는 경우 (Computer 클래스가 DeskTop 클래스에게 상속하는 경우)
Computer는 추상 클래스이다. 추상 클래스를 상속받은 클래스는 추상 클래스가 가진 메서드를 상속받는다. 따라서 상속 받은 클래스는 추상 메서드를 포함한다. 그렇기 때문에 상속 받은 클래스인 DeskTop 클래스는 추상 메서드를 모두 구현하거나 아니면 DeskTop 클래스도 추상 클래스로 만들든가 둘 중 하나를 해야한다.
즉, 추상 클래스를 상속 받은 하위 클래스는 구현되지 않은 추상 메서드를 모두 구현해야 구체적인 클래스가 된다.
예를 들어 추상 메서드가 두 개인데 그 중 하나만 구현하면 이 역시 구현이 안된 추상 메서드를 포함하는 것이므로 추상 클래스이다.

  • 추상 메서드가 없는 클래스에 abstract 예약어를 사용하는 경우
    문법상으로 추상 메서드가 없더라도 abstract 예약어를 사용하면 추상 클래스이다.
    추상 클래스는 new 예약어로 인스턴스를 생성할 수 없다.

추상 클래스를 만드는 이유

추상 클래스는 인스턴스로 생성할 수 없다. 추상 클래스는 모든 메서드가 구현되지 않았으므로 인스턴스로 생성할 수 없다.
추상 클래스에서도 형 변환은 가능하다.

추상 클래스는 상속을 하기 위해 만든 클래스이다. 실제 하위 클래스에서 내용을 각각 다르게 구현해야 한다면, 구현 내용을 추상 메서드로 남겨두고 하위 클래스에 구현을 위임하는 것이다.

구현된 메서드: 하위 클래스에서 공통으로 사용할 구현된 코드, 하위 클래스에서 재정의할 수도 있음
추상 메서드: 하위 클래스에서 구현해야할 코드, 하위 클래스마다 달라질 수 있다.

템플릿 메서드

디자인 패턴의 한 방법으로 모든 객체 지향 프로그래밍에서 사용하는 구형 방법이다.
따라서 이 구현 방법은 자바뿐만 아니라 C++, C#에서도 동일하게 적용된다.

final public void run() {
	startCar();
    	drive();
        stop();
        turnOff();
}

템플릿 메서드의 역할은 메서드 실행 순서와 시나리오를 정의하는 것이다. 템플릿 메서드에서 호출하는 메서드가 추상 메서드라면 차종에 따라 구현 내용이 바뀔 수는 있다. 템플릿 메서드는 실행 순서, 즉 시나리오를 정의한 메서드이므로 바뀔 수 없다. 상위 클래스를 상속받은 하위 클래스에서 템플릿 메서드를 재정의하면 안된다는 것이다.
그래서 템플릿 메서드는 final 예약어를 사용해 선언한다. 메서드 앞에 final을 사용하면 상속받은 하위 클래스가 메서드를 재정의할 수 없다.
템플릿 메서드는 로직 흐름이 이미 정해져 있는 프레임워크에서 많이 사용하는 기본 구현 방법이다.

final 예약어

final 예약어는 변수, 메서드, 클래스에 사용할 수 있다.

// 변수: final 변수는 상수를 의미한다.

final int NUM = 100;

상수는 변하지 않는 수이다. 상수를 선언할 때는 일반 변수와 구별하기 위해 대문자로 쓰는 경우가 많다. 상수로 선언한 수에는 다른 값을 대입할 수 없다.
프로젝트를 하다보면 여러 파일에서 똑같이 공유해야 하는 상수 값도 있다. 이런 값을 파일마다 선언하면 코드가 중복될 뿐만 아니라 값이 변하거나 추가될 때 그 값을 사용하는 모든 파일을 수정해야 한다.
따라서 자바로 프로젝트를 진행할 때 여러 파일에서 공유해야 하는 상수 값은 한 파일에 모아 public static final로 선언하여 사용하면 좋다.

public class Define {
	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 = 2.14;
        public static final String GOOD_MORNING = "Good Morning!";
}

상수를 모두 public 예약어로 선언했으므로 이들 값은 외부에서도 사용할 수 있다.
그리고 모든 상수를 static으로 선언했기 때문에 인스턴스를 생성하는 것과 관계없이 클래스 이름으로 참조할 수 있다.

메서드: final 메서드는 하위 클래스에서 재정의할 수 없다.
클래스: final 클래스는 상속할 수 없다.

클래스를 final로 선언하면 상속할 수 없다. 상속을 하면 변수나 메서드를 재정의할 수 있는데, 그러면 원래 클래스가 가지고 있는 기능에 오류가 생길 수도 있다. 따라서 보안과 관련되어 있거나 기반 클래스가 변하면 안되는 경우에 클래스를 final로 선언한다. JDK에서 제공하는 클래스 중에도 final로 선언한 클래스가 있다. 대표적으로 String이나 Integer가 있다.

TDD(Test Driven Development)

테스트 코드를 먼저 개발하는 방법론을 테스트 주도 개발이라고 한다.

정리

  • 클래스를 구현할 때 메서드 몸체를 구현하지 않고 선언만 하는 메서드를 추상 메서드라고 하고, 이를 포함한 클래스를 추상 클래스라고 한다.
  • 상수를 선언할 때나 상속받은 클래스에서 메서드를 재정의하지 못하도록 사용하는 예약어는 final이다.
  • 추상 클래스나 추상 메서드를 선언할 때 사용하는 예약어는 abstract이다.
  • 로직 흐름을 정의한 메서드이며 메서드 내부에서 일반 메서드나 구현되지 않은 추상 메서드를 호출한다.
    흐름이 변하지 않도록 하위 클래스에서 재정의하지 못하게 final로 선언하는 메서드를 템플릿 메서드라고 한다.

출처

Doit 자바 프로그래밍 입문

profile
정팔입니다.

0개의 댓글