인터페이스(interface)
이전에는 코드가 구현하지 않은 메서드를 가지고 있는 추상(abstract) 클래스를 포스팅했다. 다음으로 배울 인터페이스는 모든 메서드가 추상 메서드로만 이루어져있다고 한다. 인터페이스를 어떻게 사용하는지와 인터페이스와 다형성의 관계를 포스팅하겠습니다.
인터페이스란?
인터페이스는 메서드 구현된 코드가 없는 추상 메서드와 상수로만 이루어져 있다. 구현된 코드가 없고 형식적인 선언만 있으므로 인스턴스로 생성이 불가능하다. 설계의 용도로 사용된다.
어떤 클래스가 특정 인터페이스를 사용한다면 그 클래스는 해당 인터페이스의 메서드들을 구현해야 한다.
▶ 인터페이스 생성
인터페이스는 따로 생성할 수 있으나 파일 확장자나 문법적인 변화가 크지 않으므로 기존 클래스에서 'class'를 'interface'로 대치해주면 된다.
public interface Calc { //인터페이스 생성하기
double PI = 3.14; //인터페이스에서 선언한 변수는 컴파일 과정에서 상수로 변환됨
int ERROR = -99999999;
int plus(int num1, int num2); //메서드들은 추상 메서드로 변환됨
int minus(int num1, int num2);
int multi(int num1, int num2);
int div(int num1, int num2);
}
public class Calculator implements Calc{
public int plus(int num1, int num2) {
return num1+num2;
}
public int minus(int num1, int num2) {
return num1-num2;
}
public int multi(int num1, int num2) {
return num1*num2;
}
public int div(int num1, int num2) {
return num1/num2;
}
}
이 처럼 클래스 'Calculator'는 인터페이스 'Calc'를 구현(implements)한다라고 명시했기 때문에 인터페이스 'Calc'에 있는 메서드들을 구현해야 한다. 구현하지 않으면 컴파일 에러가 발생된다. 여러 개발자가 참여하는 프로젝트나 대형 프로젝트를 개발할 때 이정표 역할을 한다.
▶ 인터페이스 규칙
- 하나의 클래스가 여러 인터페이스를 구현할 수 있다.
- 인터페이스도 상속이 가능하다.
- 상속받은 인터페이스를 사용하려면 상속한 부모 클래스의 메서드도 반드시 구현해야 한다.
- 인터페이스의 멤버는 반드시 public을 사용해야 한다.
▶ 인터페이스 형 변환
인터페이스는 추상 메서드와 상수로만 이루어진 틀같은 존재라고 설명했다. 이 인터페이스를 구현한 클래스는 인터페이스 형으로 선언한 변수로 형 변환할 수 없다. 여러 인터페이스를 구현할 수 있고 형 변환 시 사용할 수 있는 메서드는 인터페이스에 선언된 메서드만 사용할 수 있다. 한 번에 여러 인터페이스를 상속받을 수 있다.
Calc c1 = new Calc(); //<- 에러
Calc c2 = new Calculator();
인터페이스의 요소
- 상수 : 인터페이스의 모든 변수는 값이 변하지 않는 상수로 변환됨
- 추상 메서드 : 모든 정의한 메서드는 추상 메서드로 변환됨
- 디폴트(default) 메서드 : 기본 구현을 가진 메서드로 구현 클래스에서 재정의 할 수 있음(Java8부터 추가됨)
- 정적(static) 메서드 : 인스턴스 생성과 상관없이 인터페이스 타입으로 사용할 수 있는 메서드(Java8부터 추가됨)
- private 메서드 : 인터페이스를 구현한 클래스에서 사용하거나 재정의 할 수 없음. 인터페이스 내부에서만 기능을 제공(Java8부터 추가됨)
▶디폴트(default) 메서드
인터페이스에서는 상수와 추상 메서드만 있다고 했지만 Java8 버전 이후 디폴트 메서드가 생겼다. 즉, 구현 코드를 가지고 있는 메서드를 작성할 수 있다는 말이다. 사용 방법은 아래와 같이 'default' 예약어를 메서드 앞에 붙여 사용한다.
default defaultMethod() {
System.out.println("디폴트 메서드 입니다.");
}
하나의 인터페이스는 여러 클래스들로 구현되어 있을 수 있기 때문에 공통으로 사용될 메서드를 디폴드 메서드에 작성하면 되겠다.
하지만! 다른 클래스에서 필요한 기능이 아닐 경우, 디폴트 메서드를 다른 클래스에서 오버 라이딩해 사용할 수 있다.
- 1. 디폴트 메서드는 인터페이스에서 코드 구현을 가능하게 한다.
- 2. 디폴트 메서드는 해당 인터페이스를 사용하는 클래스에서 오버 라이딩할 수 있다.
▶정적(static) 메서드
정적 메서드 또한 디폴트 메서드와 마찬가지로 인터페이스에서 코드 구현이 가능하며, 인스턴스 생성과 상관없이 메서드를 사용할 수 있다.
static staticMethod() {
System.out.println("정적 메서드 입니다.");
}
- 1. 정적 메서드는 인터페이스에서 코드 구현을 가능하게 한다.
- 2. 정적 메서드는 디폴트 메서드와 다르게 인스턴스 생성을 하지 않아도 사용이 가능하다.
▶private 메서드
인터페이스 내부에 private 또는 private static 예약어를 사용하여 선언한다. private static은 정적(static) 메서드에서만 사용할 수 있다. 인터페이스를 구현한 클래스에서 사용할 수 없고 인터페이스 내부에서만 사용하기 위해 구현된다.
인터페이스 상속
인터페이스도 상속(extends)이 가능하며 상속받은 메서드들은 인터페이스를 구현하는 클래스가 모두 구현해야 한다.