728x90
인터페이스?
- 앞선 장에서는 구현하지 않은 메서드를 포함한 추상 클래스에 대해 배웠습니다.
- 이제 모든 메서드가 추상 메서드로만 이루어진 인터페이스에 대해 알아보겠습니다.
- 구현 코드가 없는 인터페이스가 어떤 쓰임이 있는지, 클래스가 인터페이스를 구현하는 것은 어떤 의미인지 살펴봅시다.
- 인터페이스와 다형성의 관계를 이해함으로써 자바 프로그램을 만들 때 인터페이스 설계가 왜 중요한지도 알 수 있습니다.
구현 코드가 없는 인터페이스
- 인터페이스(Interface)는 클래스 혹은 프로그램이 제공하는 기능을 명시적으로 선언하는 역할을 합니다.
- 인터페이스는 추상 메서드와 상수로만 이루어져 있습니다.
- 구현된 코드가 없기 때문에 당연히 인터페이스로 인스턴스를 생성할 수도 없습니다.
- 그렇다면 구현 코드도 없는 인터페이스는 어떻게 사용하는 걸까요?
- 인터페이스를 직접 만들어 보면서 살펴봅시다.
인터페이스 만들기
- 인터페이스를 사용해 간단한 계산기 프로그램을 만들어 보겠습니다.
- 이클립스에서 인터페이스를 만들 때는 New - Interface 를 클릭하여 생성합니다.
public interface Calc {
double PI = 3.14; // 인터페이스에서 선언한 변수는 컴파일 과정에서 자동으로 상수로 변환됨
int ERROR = -99999;
int add(int num1, int num2); // 인터페이스에서 선언한 메서드는 컴파일 과정에서 자동으로 추상 메서드로 변환됨
int substract(int num1, int num2);
int times(int num1, int num2);
int divide(int num1, int num2);
}
- 이 인터페이스는 계산기를 만들기 위해 선언한 코드입니다.
- Calc 인터페이스에는 원주율을 뜻하는 PI 변수와 오류가 났을 때 사용할 ERROR 변수, 그리고 사칙연산에 해당하는 메서드 4개를 선언했습니다.
- 인터페이스에 선언한 변수는 public static final 예약어를 쓰지 않아도 컴파일 과정에서 자동으로 상수로 변환됩니다.
- 인터페이스에 선언한 메서드는 public abstract 예약어를 쓰지 않아도 컴파일 과정에서 자동으로 추상 메서드로 변환됩니다.
클래스에서 인터페이스 구현하기
- 클래스가 인터페이스를 사용하는 것을 '클래스에서 인터페이스를 구현한다 implement' 라고 표현합니다.
- 인터페이스에 선언한 기능을 클래스가 구현한다는 의미로 implements 예약어를 사용합니다.
- Calc 인터페이스를 Calculator 클래스에서 구현하는 방법은 다음과 같습니다.
public class Calculator implements Calc{ // 오류 발생
}
- 그런데, 이렇게 코드를 작성하면 다음과 같은 오류가 발생합니다.
- 1. 구현하지 않은 추상 메서드를 구현하세요.
- 2. Calculator 클래스를 추상 클래스로 만드세요.
- 이러한 오류가 발생하는 이유는 Calculator 클래스에서 Calc 인터페이스를 구현한다고 했으므로 Calculator 클래스는 추상 메서드 4개를 포함합니다.
- 따라서 인터페이스를 구현하면서 받은 추상 메서드를 구현하지 않으면 Calculator 클래스도 추상 메서드가 되어야 하기 때문에 에러 메시지가 나오게 됩니다.

- 클래스 다이어그램에서 인터페이스를 구현하는 것은 점선으로 표시합니다.
- 우선 Calc 의 4가지 추상 메서드 중 2가지만 Calculator 에서 구현해보겠습니다.
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;
}
}
- 위의 Calculator 클래스는 Calc 인터페이스를 구현하는데, 4개의 추상 메서드 모두 구현하지 않고 2개만 구현했으므로 추상 클래스가 됩니다.
- 이제 모든 메서드를 구현한 CompleteCalc 계산기 클래스를 만들어 보겠습니다.
- CompleteCalc 클래스에서는 Calculator 클래스를 상속받아 CompleteCalc 클래스를 만듭니다.

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;
}
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();
System.out.println(calc.ERROR);
}
}
- CompleteCalc 자료형 변수 calc 를 생성하고 해당 변수에 CompleteCalc 의 인스턴스를 담았습니다.
- 왜냐하면 CompleteCalc 클래스만 구체적인 클래스이고 나머지 클래스들은 인스턴스를 생성할 수 없는 추상 클래스이거나 인터페이스이기 때문입니다.
- 그리고 calc 변수로 재정의된 메서드들인 add, substract, times, divide 와 CompleteCalc 클래스에서 정의한 메서드인 showInfo 메서드를 성공적으로 사용하여 결과값을 출력하는 것을 볼 수 있습니다.
- 여기서 궁금한 것이 하나 있지 않으신가요?
- calc.ERROR 이 코드는 어떻게 작동하는 걸까요?
- 다른 메서드들은 interface 를 구현하거나 상속을 받은 다음 메서드를 재정의 하는 과정을 통해 메서드를 사용할 수 있게 되었습니다.
(제가 이해한 바로는 다음과 같습니다만, 아주 잘못된 이해 방식일 수 있음을 미리 말씀드립니다. 추후에 수정해야겠다는 깨달음이 있다면 바로 수정하러 오겠습니다.)인터페이스를 구현하는 클래스는 인터페이스의 모든 것을 구현해야 합니다.우리의 예제를 통해서 생각해 보자면, Calc 인터페이스를 implement 한 Calculator 클래스는 Calc 인터페이스에 있는 모든 멤버들을 implement 해야 합니다.따라서 Calc 인터페이스에서 정의한 ERROR 와 같은 상수는 Calc 인터페이스를 implement 한 Calculator 클래스에 들어있고, Calculator 클래스를 상속 받은 CompleteCalc 클래스의 인스턴스를 통해서 ERROR 상수를 사용할 수 있습니다.- * 수정 *
- 제가 이해했던 내용이 틀렸습니다. 이전과 마찬가지로 제가 이해한 내용이 틀리면 수정하러 다시 오겠습니다.
- 상수 데이터는 스택 메모리나 힙 메모리에 생성되는 것이 아니라 데이터 영역에 바로 생성됩니다.
- 따라서 Calc 인터페이스에 int ERROR 로 선언한 변수는 컴파일러가 자동으로 public static final 로 선언하기 때문에 상수로 정의됩니다.
- 따라서 Calc 인터페이스 밖 클래스에서 Calc 인터페이스 명으로 해당 상수를 자연스럽게 사용할 수 있습니다.
인터페이스 구현과 형 변환

- 우리의 예제를 다시 살펴보겠습니다.
- Calculator 클래스는 인터페이스에서 선언한 추상 메서드 중 일부 메서드만 구현했으므로 당연히 추상 클래스입니다.
- 그리고 Calculator 클래스를 상속 받은 CompleteCalc 클래스에서 Calculator 클래스에서 구현하지 않은 나머지 추상 메서드를 모두 구현하고 showInfo( ) 메서드를 추가로 구현했습니다.
- 이런 과정에서 하위 클래스의 형 변환은 어떻게 이루어지는지 살펴보겠습니다.
- 상속 관계에서 하위 클래스는 상위 클래스 자료형으로 묵시적 형 변환할 수 있다고 했습니다.
- 인터페이스도 마찬가지입니다.
- CompleteCalc 클래스는 상위 클래스인 Calculator 형이면서, Calc 인터페이스를 구현하였으므로 Calc 형이기도 합니다.
- 그래서 다음과 같이 Calc 형으로 선언한 변수에 CompleteCalc 의 인스턴스를 대입할 수 있습니다.
Calc calc = new CompleteCalc( );
- 이 calc 변수가 사용할 수 있는 메서드를 살펴볼까요?
- Calc 에서 선언한 추상 메서드들(add, substract, times, devide)은 사용 가능합니다.
- 그런데, CompleteCalc 클래스에서 추가로 구현한 showInfo( ) 메서드는 사용 불가능합니다.
- 즉 Calc 형으로 선언한 변수에서 사용할 수 있는 메서드는 Calc 인터페이스에 선언한 메서드뿐입니다.
정리하자면
- 인터페이스를 구현한 클래스는 해당 인터페이스형으로 묵시적 형 변환이 가능합니다.(상속과 같다)
- 형 변환되었을 때 사용할 수 있는 메서드와 상수는 인터페이스에서 선언한 메서드와 상수입니다.
'[그린컴퓨터] Server > JAVA(객체 지향 프로그래밍)' 카테고리의 다른 글
| 인터페이스 요소 살펴보기 { 인터페이스 상수, 디폴트 메서드와 정적 메서드, 디폴트 메서드, private 메서드 } (0) | 2023.06.04 |
|---|---|
| 인터페이스와 다형성 { 인터페이스의 역할, 인터페이스와 다형성, 클라이언트가 클래스를 사용하는 방법 } (0) | 2023.06.04 |
| final 예약어 { 상수를 의미하는 final 변수, 상속할 수 없는 final 클래스, TDD } (0) | 2023.06.01 |
| 템플릿 메서드 응용하기 { 예제 이해하기, 클래스 기능과 관계, 클래스 설계하기, 추상 클래스와 다형성 } (0) | 2023.06.01 |
| 템플릿 메서드 { 추상 클래스와 템플릿 메서드, 템플릿 메서드의 역할, final } (0) | 2023.06.01 |