본문 바로가기

BackEnd/Java

구현 코드가 없는 인터페이스 (interface)

인터페이스(interface)는 클래스 혹은 프로그램이 제공하는 기능을 명시적으로 선언하는 역할을 하며 추상 메서드와 상수로만 이루어져 있고 구현된 코드가 없기 때문에 인터페이스로 인스턴스를 생성할 수도 없습니다.

 

인터페이스를 생성하려면 클래스를 생성할 때 처럼 패키지에서 마우스 우클릭 후 [New -> Interface]를 클릭하여 생성하며 간단한 계산기 인터페이스를 만들어보겠습니다.

 

public interface Calc {
	double PI = 3.14;
	int ERROR = -999999999;

	int add(int num1, int num2);
	int substract(int num1, int num2);
	int times(int num1, int num2);
	int divide(int num1, int num2);
}

 

인터페이스에서 선언한 변수는 모두 컴파일 과정에서 값이 변하지 않는 상수로 자동 변환되고 public static final 예약어를 쓰지 않아도 무조건 상수로 인식되고 인터페이스에서 선언한 메서드도 마찬가지로 모두 public abstract 예약어가 없어도 컴파일 과정에서 구현 코드가 없는 추상 메서드로 변환됩니다.

 


 

클래스에서 인터페이스 구현하기

이렇게 선언한 인터페이스를 클래스가 사용하는 것을 '클래스에서 인터페이스를 구현한다 (implements)'라고 표현합니다. 상속에서 상위 클래스에 구현한 기능을 하위 클래스에서 확장한다는 의미로 extends 예약어를 사용하였는데, 인터페이스에서는 인터페이스에 선언한 기능을 클래스가 구현한다는 의미로 implements 예약어를 사용합니다.

위에서 만든 Calc 인터페이스를 Calculator 클래스에서 구현하는 방법은 다음과 같습니다.

 

public class Calculator implements Calc {

}

 

인터페이스를 상속받을 경우 implements가 아닌 extends 예약어를 사용합니다.

 

그런데 이렇게 코드를 작성하면 Calculator 클래스에 다음과 같은 오류가 표시됩니다.

 

 

문제 해결 1. 추상 메서드 구현하기

문제 해결 2. Calculator 클래스를 추상 클래스로 만들기

 

Calculator 클래스에서 Calc 인터페이스를 구현한다고 선언 했으므로 Calculator 클래스는 추상 메서드 4개(add(), substract(), times(), divide())를 포함합니다. 이 추상 메서드를 구현하지 않으면 Calculator 클래스도 추상 클래스가 됩니다. 즉 위 오류 메시지는 Calc 인터페이스에 포함된 추상 메서드를 구현하거나 Calculator 클래스를 추상 클래스로 만들라는 의미입니다.

 

우선은 문제 해결 1번의 Add umimplemented methods 옵션을 클릭하여 Calc 인터페이스에 선언한 4개 추상 메서드 중 add()와 abstract() 2개만 구현하여 추상 클래스로 만든 후 이를 상속하는 클래스를 만드는 과정으로 구현해보겠습니다.

 

public abstract class Calculator implements Calc { // 추상 클래스

	@Override
	public int add(int num1, int num2) {
		return num1 + num2;
	}

	@Override
	public int substract(int num1, int num2) {
		return num1 - num2;
	}
}

 

추상 메서드 times()와 divide()를 구현하지 않았으므로 Calculator는 추상 클래스입니다.

 


 

클래스 완성하고 실행하기

이제 모든 메서드를 구현한 계산기 클래스를 만들어 보겠습니다. Calculator 추상 클래스를 상속받아 CompleteCalc 클래스를 만듭니다. 아직 구현하지 않은 times()와 divide() 추상 메서드를 이 클래스에서 구현합니다.

 

public class CompleteCalc extends Calculator {

	@Override
	public int times(int num1, int num2) {
		return num1 * num2;
	}

	@Override
	public int divide(int num1, int num2) {
		if(num2 != 0) return num1 / num2;
		else return Calc.ERROR; // num2가 0, 즉 나누는 수가 0인 경우에 대해 오류 반환
		
	}
	
	public void showInfo() {
		System.out.println("Calc 인터페이스를 구현하였습니다.");
	}
	
}

 

- CompleteCalc 클래스 실행하기

 

public class CalculatorTest {

	public static void main(String[] args) {

		int num1 = 10;
		int num2 = 5;
		
		CompleteCalc calc = new CompleteCalc();
		
		System.out.println(calc.add(num1, num2));
		System.out.println(calc.substract(num1, num2));
		System.out.println(calc.times(num1, num2));
		System.out.println(calc.divide(num1, num2));
		
		calc.showInfo();
	}

}

 

- 실행 결과

 

 

num1(10)과 num2(5)를 덧셈, 뺄셈, 곱셈, 나눗셈 연산한 결과 값을 출력했습니다. 8행을 보면 구체적인 클래스인 CompleteCalc 클래스만 인스턴스를 생성할 수 있고 Calculator 클래스는 추상 클래스이므로 인스턴스를 생성할 수 없고, Calc 인터페이스는 추상 메서드만으로 선언되었기 때문에 인스턴스를 생성할 수 없습니다.


 

인터페이스 구현과 형 변환

Caculator 클래스는 인터페이스에서 선언한 추상 메서드 중 일부 메서드만 구현했으므로 추상 클래스입니다. 그리고 이를 상속받은 CompleteCalc 클래스는 Calculator 클래스에서 구현하지 않은 나머지 추상 메서드를 모두 구현하고 showInfo() 메서드를 추가로 구현했습니다. 이러한 관계에서 하위 클래스의 형 변환은 어떻게 이루어지는지 보겠습니다.

 

상속 관계에서 하위 클래스는 상위 클래스 자료형으로 묵시적 형 변환이 가능합니다. 인터페이스도 마찬가지입니다. CompleteCalc 클래스는 상위 클래스인 Calculator형이면서, Calc 인터페이스를 구현하였으므로 Calc형이기도 합니다. 따라서 별다른 조치 없이 다음처럼 Calc형으로 선언한 변수에 대입할 수 있습니다.

 

Calc calc = new CompleteCalc();

 

그러면 calc 변수를 Calc형 변수인 newCalc에 대입하고 자동완성을 보고 newCalc 변수가 사용할 수 있는 메서드를 살펴봅시다. Calc에서 선언한 추상 메서드는 있지만, CompleteCalc 클래스에서 추가로 구현한 showInfo() 메서드는 없습니다. 즉 Calc형으로 선언한 변수에서 사용할 수 있는 메서드는 Calc 인터페이스에 선언한 메서드뿐입니다.

 

정리하자면, 인터페이스를 구현한 클래스가 있을 때 그 클래스는 해당 인터페이스형으로 묵시적 형 변환이 이루어지며, 형 변환되었을 때 사용할 수 있는 메서드는 인터페이스에서 선언한 메서드뿐입니다. 각 자료형에서 사용할 수 있는 메서드를 표로 나타내면 다음과 같습니다.

 

Calc형 변수와 Calculator형 변수에서

사용 가능

add()

CompleteCalc형 변수에서

사용 가능

substract()
times()
devide()
X showInfo()

* 중앙을 기준으로 좌우로 보세요 *

 


 

인터페이스의 역할

  • 구현의 강제로 표준화
  • 인터페이스를 통한 간접적인 클래스 사용으로 손쉬운 모듈 교체 지원
  • 서로 상속의 관계가 없는 클래스들에게 인터페이스를 통한 관계 부여로 다형성 확장
  • 모듈 간 독립적 프로그래밍으로 개발 시간 단축
  • 어떤 기능의 메서드를 제공하는지 명시

'BackEnd > Java' 카테고리의 다른 글

[기본 클래스] Object 클래스  (0) 2020.04.05
enum (데이터 열거형 타입)  (1) 2020.03.23
향상된 for문 (for each문)  (0) 2020.03.23
추상화 (Abstract)  (0) 2020.03.16
상수 (final)  (0) 2020.03.16