본문으로 바로가기

1. 인터페이스 역할

인터페이스 역할

  • 인터페이스는 객체의 사용 방법을 정의한 타입
  • 인터페이스는 객체의 교환성을 높여주기 때문에 다형성을 구현하는데 매우 중요한 역할
  • 인터페이스는 개발 코드와 객체가 서로 통신하는 접점 역할
  • 개발 코드가 인터페이스의 메소드를 호출하면 인터페이스는 객체의 메소드를 호출
  • 개발 코드는 객체의 내부 구조를 알 필요가 없고 인터페이스의 메소드만 알고 있으면 됩니다.

 

왜 중간에 인터페이스를 두는 가요?

  • 개발 코드를 수정하지 않고, 사용하는 객체를 변경할 수 있도록 하기 위해서입니다.
  • 인터페이스는 하나의 객체가 아니라 여러 객체들과 사용이 가능하므로 어떤 객체를 사용하느냐에 따라서 실행 내용과 리턴 값이 다를 수 있습니다. (다형성)
  • 객체 교환을 이용해서 다양한 리턴 값을 반환받을 수 있습니다. (부품화)

 

2. 인터페이스 선언

public interface 인터페이스명 {
    // 상수
    타입 상수명 = 값;
    
    // 추상 메소드
    타입 메소드명(매개변수, ...);
    
    // 디폴트 메소드
    default 타입 메소드명(매개변수, ...) {
        ...
    }
    
    // 정적 메소드
    static 타입 메소드명(매개변수, ...) {
        ...
    }
}
  • 인터페이스는 상수메소드만을 구성 멤버로 가집니다.
  • 인터페이스는 객체로 생성할 수 없기 때문에 생성자를 가질 수 없습니다.
  • 자바 7 이전까지는 인터페이스의 메소드는 실행 블록이 없는 추상 메소드로만 선언이 가능
  • 자바 8부터는 디폴트 메소드정적 메소드도 선언이 가능

 

3. 인터페이스 구성요소

상수 필드 (Constant Field)

[public static final] 타입 상수명 = 값;
  • 인터페이스는 런타임 시 데이터를 저장할 수 있는 필드(인스턴스, 정적필드)를 선언할 수 없습니다.
  • 상수를 선언할 때는 반드시 초기값을 대입해야 합니다.
  • 인터페이스 상수 필드는 static {} 블록으로 초기화할 수 없기 대문에 반드시 선언과 동시에 초기값을 지정해야 합니다.
  • public static final을 생략하더라도 자동적으로 컴파일 과정에서 붙게 됩니다.

 

추상 메소드 (Abstract Method)

[public abstract] 리턴타입 메소드명(매개변수, ...);
  • 추상 메소드는 리턴타입, 메소드명, 매개 변수만 기술되고 중괄호 {}를 붙이지 않는 메소드입니다.
  • 구현 클래스에서 구현해야 하는 메소드입니다.
  • public abstract 선언 생략하더라도 자동적으로 컴파일 과정에서 붙게 됩니다.

 

디폴트 메소드 (Default Method)

[public] default 리턴타입 메소드명(매개변수, ...) { 
    // ... (실행 내용)
}
  • 자바 8에서 추가된 인터페이스의 새로운 멤버
  • default 키워드가 리턴 타입 앞에 붙습니다.
  • 디폴트 메소드는 인스턴스 메소드이므로 구현 객체가 있어야 사용할 수 있습니다.
  • 디폴트 메소드는 인터페이스의 모든 구현 객체가 가지고 있는 기본 메소드
  • 구현 클래스 작성 시 디폴트 메소드를 오버라이딩해서 해당 구현 클래스에 맞게 수정할 수 있습니다.
  • 디폴트 메소드는 public 특성을 갖기 때문에 public을 생략하더라도 자동적으로 컴파일 과정에서 붙게 됩니다.

 

정적 메소드 (Static Method)

[public] static 리턴타입 메소드명(매개변수, ...) { 
    // ... (실행 내용)
}
  • 자바 8에서 추가된 인터페이스의 새로운 멤버
  • static 키워드가 리턴 타입 앞에 붙습니다.
  • 객체가 없어도 인터페이스만으로 호출이 가능합니다.
  • 정적 메소드는 public 특성을 갖기 때문에 public을 생략하더라도 자동적으로 컴파일 과정에서 붙게 됩니다. 

 

4. 인터페이스 구현 (implement)

구현 클래스

public class 구현클래스명 implments 인터페이스명 {
	// 인터페이스에 선언된 추상 메소드의 실체 메소드 선언
}
  • implements 키워드
  • 인터페이스에 선언된 추상 메소드의 실체 메소드 선언

 

예시

인터페이스 A

public interface A {
    // 상수
    String interfaceName = "A";
    // 추상 메소드
    void printImplementClassName();
    // 디폴트 메소드
    default void printHello() {
        System.out.println("Hello");
    }
    // 정적 메소드
    static void printInterfaceName() {
        System.out.println(interfaceName);
    }
}

 

인터페이스 A의 구현 클래스 AImpl

public class AImpl implements A {
    @Override
    public void printImplementClassName() {
        System.out.println("AImpl");
    }

    // 디폴트 메소드를 오버라이딩 할 수도 있습니다.
//    @Override
//    public void printHello() {
//        System.out.println("안녕하세요!");
//    }
}

 

실행

// 정적 메소드 사용
A.printInterfaceName(); // A

// 구현 객체 생성
A a = new AImpl();

// 디폴트 메소드 사용
a.printHello(); // Hello

// 추상 메소드 사용
a.printImplementClassName(); // AImpl

 

다중 인터페이스 구현 클래스​

  • 다중 인터페이스를 구현할 경우, 구현 클래스는 모든 인터페이스의 추상 메소드에 대해 실체 메소드를 작성해야 합니다.
  • 만약 추상 메소드를 하나라도 구현하지 않을 경우 추상 클래스로 선언해야 합니다.

 

예시

인터페이스 OnEvent

public interface OnEvent {
    void on();
}

 

인터페이스 OffEvent

public interface OffEvent {
    void off();
}

 

인터페이스 OnEvent, OffEvent의 구현 클래스 MacBook

public class MacBook implements OnEvent, OffEvent {
    @Override
    public void on() {
        System.out.println("Mac Book On");
    }

    @Override
    public void off() {
        System.out.println("Mac Book Off");
    }
}

 

추상 메소드를 하나라도 구현하지 않을 경우 추상 클래스로 선언 필요 (주의)

public abstract class MacBook implements OnEvent, OffEvent {
    @Override
    public void on() {
        System.out.println("Mac Book On");
    }
}​