인터페이스(Interface)
는 추상클래스의 일종으로, 추상클래스와 마찬가지로 다른 클래스를 작성하는데 도움을 주기 위한 클래스입니다. 추상클래스의 일종이기 때문에 인터페이스
또한 인스턴스를 생성할 수 없습니다.
추상클래스와 인터페이스의 차이는 추상클래스
는 일부는 구현이 되었지만 일부는 추상메소드로 남아있는 미완성된 클래스이고, 인터페이스
는 모든 부분이 미구현되어 기본적인 설계도만 제공하기 때문입니다.
즉, 인터페이스는 추상클래스보다 추상화 정도가 더 높습니다.
정말 단순하게 표현하자면 인터페이스는 그림의 스케치이고, 추상클래스는 스케치에서 일부분을 완성한 것이라고 할 수 있습니다.
인터페이스는 class
대신 interface
명령을 사용해서 선언합니다.
interface 인터페이스명 {}
인터페이스의 접근제어자로는 public 또는 default를 사용할 수 있습니다. public 선언은 어디에서나 접근 가능함과 동시에 파일명과 인터페이스명이 일치해야합니다.
인터페이스는 일반적으로 형용사형태를 담아서 작명합니다. 따라서 -able
이라는 접미사를 붙일 수 있다면 붙여서 작명하는 것이 좋다고 합니다. -able
없이도 동작을 이름에 담아낼 수 있다면 -able
을 붙이지 않아도 됩니다.
또한 과거에는 인터페이스임을 나타내기위해 접두사로 I-
를 사용하기도 했었는데 이 방식은 지양되고 있는 헝가리안 표기 방식이므로 사용하지 않습니다.
인터페이스와 그 구현체를 구분하기 위해서 구현체 클래스에 접미사
-Impl
을 붙이는 경우도 있습니다.
물론 위 내용들은 권장사항이거나 유명한 몇몇 코딩 컨벤션의 내용이기에 위 내용보다는 속한 그룹의 코딩 컨벤션을 따르는 것이 좋습니다.
인터페이스
의 멤버로는 public static final 멤버 변수(상수)와 추상 메소드가 올 수 있습니다.
물론 이 외에도 디폴트 메소드, 클래스메소드, private 메소드가 올 수 있지만 기본적으로 상수와 추상 메소드가 오기에 여기서는 두 가지만 다룹니다. 나머지 내용은 해당 포스트를 참조해주세요.
interface 인터페이스명 {
public static final 타입 변수명 = 값; //상수
public abstract 메소드명(); //추상메소드
}
인터페이스
의 멤버로 오직 public static final 멤버 변수(상수)와 추상 메소드
만이 오기 때문에 제어자(public static final, public abstract
)를 생략할 수 있습니다. 생략한 선언은 컴파일 과정에서 컴파일러에 의해 자동적으로 추가되어 컴파일 됩니다.
인터페이스끼리도 서로 상속을 할 수 있습니다. 이때 단일 상속만을 지원하는 클래스와는 다르게 인터페이스끼리는 다중 상속이 가능합니다.
interface Fruit {
public abstract void printTasty();
}
interface Food { }
public interface Apple extends Fruit, Food { }
Fruit 인터페이스를 상속받은 Apple 인터페이스는 Fruit의 printTasty()
추상메소드를 멤버로 가지게 됩니다.
인터페이스를 구현하기 위해서는 인터페이스의 추상메소드를 구현할 클래스를 하나 만들어야합니다. 이때 인터페이스
는 클래스 상속이나 추상클래스처럼 확장(extends)의 개념이 아닌 구현의 개념이므로 implments
키워드를 사용합니다.
위에서 구현한 Apple 인터페이스를 구현한 클래스입니다.
public class AppleImpl implements Apple {
@Override
public void printTasty() {
System.out.println("아삭아삭");
}
}
public class Main {
public static void main(String[] args) {
AppleImpl apple = new AppleImpl();
apple.printTasty();
}
}
사실 지금까지의 내용만 보면 인터페이스의 기본 개념만 설명했기 때문에 추상메소드와 다를 것도 없고 왜 인터페이스를 써야하는지 살짝 긴가민가하실 수도 있는데요. 인터페이스 사용시의 장점은 다음과 같습니다.
독립적인 프로그래밍이 가능하다
클래스의 선언과 구현을 분리할 수 있기 때문에 간접적인 연관 관계가 되어서 독립적인 프로그래밍이 가능해집니다. 독립적인 프로그래밍은 한 클래스(인터페이스)의 변경이 연관있는 다른 클래스에 영향을 주지 않음을 의미합니다.
관련성이 없는 클래스 간 관계를 맺어줄 수 있다
조상과 자손 관계(상속)이 아닌 클래스 사이에 인터페이스라는 연결부를 놓아 서로 간접적인 연관 관계를 더할 수 있습니다.
개발시간 단축이 가능하다
인터페이스와 구현 클래스를 통해 분업이 쉬워지고 개발이 빨라진다.
이번 포스트에서는 인터페이스의 기본 개념과 선언, 구현에 대해서만 알아봤습니다. 앞으로 두 개 정도의 포스트를 통해 인터페이스를 조금 더 깊게 알아보려고 합니다.