티스토리 뷰

Java

자바 인터페이스(Interface)

J-Mandu 2022. 4. 13. 09:00

인터페이스란?

클래스들이 구현해야 하는 동작들을 추상적으로 선언하는 추상 자료형입니다.

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() 메소드를 통하여 핸드폰 사이즈 및 모델명(대문자 변환)을 테스트해보았습니다.

 

이로써 공부한 내용을 간략히 정리해보았습니다. 

감사합니다.


출처

https://www.inflearn.com/course/the-java-java8/dashboard