자바 인터페이스(Interface)
인터페이스란?
클래스들이 구현해야 하는 동작들을 추상적으로 선언하는 추상 자료형입니다.
Interface라는 키워드를 사용하여 선언합니다.
강제적으로 구현해야 하는 추상 메소드가 있으며, static과 final이 둘 다 선언되는 상수가 있습니다.
자바 8버전부터, default 메소드와 static 메소드를 인터페이스에 구현할 수 있습니다.
기존 자바 7버전 이하에서는 추상화 클래스에서 공통코드를 구현체 메소드로 구현하여 상속 할 경우
추상화 클래스만 상속 받을 수 있기 때문에 더 이상 상속이 불가능하였습니다.
하지만, 자바 8버전부터는 인터페이스에서 default 메소드와 static 메소드가 추가되어 상속에 대하여 자유가 생겼습니다.
기본 메소드(Default Method)
인터페이스에 메소드를 구현할 수 있습니다.
Object가 제공하는 기능(equals, hasCode 등)은 기본 메소드로 제공할 수 없습니다.
스태틱 메소드(Static Method)
해당 타입 관련 헬퍼 또는 유틸리티 메소드를 제공할 때 인터페이스에 스태틱 메소드를 제공할 수 있습니다.
public interface HandPhone {
String getModelName();
/**
* @implSpec
* 핸드폰 스펙(Model Name)을 리턴
*/
default Map<String, String> getSpec(){
Map<String, String> map = new HashMap<>();
map.put("model", getModelName());
return map;
}
/**
* @implSpec
* 핸드폰 스펙(Model Name)을 출력
*/
default void printSpec() {
System.out.println("Model Name : " + getUpperName(getModelName()));
}
static String getUpperName(String name){
return name.toUpperCase();
}
}
기본 메소드는 해당 인터페이스를 구현한 클래스가 있을 경우 기본 메소드를 추가하여도 구현체가 깨지지 않습니다.
하지만, 기본 메소드는 구현체 모르게 추가된 기능으로 반드시 문서화를 하는 게 좋습니다.(@implSpec 자바 독 태그)
public interface IPhone extends HandPhone {
String SIZE = "71.5 × 146.7 × 7.65 mm";
void printSpec();
/**
* @implSpec
* HandPhone Interface 재정의 함수
* 핸드폰 스펙(Size, Model Name)을 리턴
*/
@Override
default Map<String, String> getSpec() {
Map<String, String> map = new HashMap<>();
map.put("size", SIZE);
map.put("model", HandPhone.getUpperName(getModelName()));
return map;
}
}
기본 메소드는 인터페이스를 상속받는 인터페이스에서 다시 추상 메소드로 변경할 수 있습니다.
또한 인터페이스 구현체가 기본 메소드를 재정의 할 수도 있습니다.
public class IPhone13 implements IPhone{
@Override
public String getModelName() {
return "IPhone13(A2633)";
}
@Override
public void printSpec() {
System.out.println("Size : " + SIZE);
System.out.println("Model Name : " + HandPhone.getUpperName(getModelName()));
}
}
추상 메소드 getModelName()과 printSpec을 구현하였습니다.
public class HandPhoneTest {
HandPhone iPhone13 = new IPhone13();
@Test
public void 모델명가져오기(){
Assertions.assertThat(iPhone13.getModelName()).isEqualTo("IPhone13(A2633)");
}
@Test
public void 스펙가져오기및출력(){
Map<String, String> iPhone13Spec = iPhone13.getSpec();
Assertions.assertThat(iPhone13Spec.size()).isEqualTo(2);
Assertions.assertThat(iPhone13Spec.get("size")).isEqualTo("71.5 × 146.7 × 7.65 mm");
Assertions.assertThat(iPhone13Spec.get("model")).isEqualTo("IPHONE13(A2633)");
iPhone13.printSpec();
}
}
IPhone 인터페이스를 구현한 IPhone13 클래스를 테스트하기 위하여 테스트 케이스를 작성하였습니다.
getModelName() 메소드로 모델명을 가져오고,
getSpec() 메소드를 통하여 핸드폰 사이즈 및 모델명(대문자 변환)을 테스트해보았습니다.
이로써 공부한 내용을 간략히 정리해보았습니다.
감사합니다.
출처