# 8. 인터페이스

# 8.1 인터페이스 역할

  • 인터페이스 : 사전적인 의미로 두 장치를 연결하는 접속기를 말한다. 여기서 두 장치를 서로 다른 객체로 본다면, 인터페이스는 이 두 객체를 연결하는 역할을 한다.
  • 중간에 인터페이스를 거치도록 하는 이유? 만약에 객체 B가 교체된다고 가정하면 객체A는 인터페이스의 메소드만 사용하므로 객체 B가 객체 C로 변경되는 것에는 관심이 없다.
  • 다형성을 구현하기 위해 인터페이스 사용

# 8.2 인터페이스와 구현 클래스 선언

  • 인터페이스는 '~java' 형태의 소스파일로 작성되고 '~.class' 형태로 컴파일 되기 때문에 물리적 형태는 클래스와 동일하다.
  • 단 소스를 작성할때 선언하는 방법과 구성 멤버가 클래스와 다르다

# 인터페이스 선언

interface 인터페이스명 {...} // default 접근제한
public interface 인터페이스명 { // public 접근 제한
    // public 상수 필드
    // public 추상 메소드
    // public 디폴트 메소드
    // public 정적 메소드
    // private 메소드
    // private 정적 메소드
}

# 구현 클래스 선언

  • 객체 A가 인터페이스의 추상 메소드를 호출하면 인터페이스는 객체 B의 메소드를 실행.
  • 객체 B는 인터페이스에 선언된 추상 메소드와 동일한 선언부를 가진 (재정의된) 메소드를 가지고 있어야 한다.
  • 여기서 객체 B를 인터페이스를 구현한 (implement) 객체라고 한다. 인터페이스에 정의된 추상 메소드에 대한 실행 내용이 구현(작성)되어 있기 때문이다.

public class B implements 인터페이스명 {..}
  • implements 키워드는 해당 클래스가 인터페이스를 통해 사용할 수 있다는 표시이며, 인터페이스의 추상 메소드를 재정의한 메소드가 있다는 뜻 이다.

# 변수 선언과 구현 객체 대입

  • 인터페이스도 하나의 타입 이므로 변수의 타입으로 사용할 수 있다.
  • 인터페이스는 참조 타입에 속하므로 인터페이스 변수에는 객체를 참조하고 있지 않다는 뜻으로 null 대입 가능
  • 인터페이스를 통해 구현 객체를 사용하려면, 인터페이스 변수에 구현 객체를 대입해야 한다.

public class Television implements RemoteControl {...}
public class Audio implements RemoteControl {...}
...
RemoteControl rc = new Television();    
rc.turnOn(); // Television 에 재 정의된 turnOn 메소드
rc = new Audio();
rc.turnOn();

# 8.3 상수 필드

  • 인터페이승에는 public static final 특성을 갖는 불변의 상수 필드를 멤버로 가질 수 있다.
  • 인터페이스에서 선언된 필드는 모두 public static final 특성을 가지기 때문에 생략하더라고 자동적으로 컴파일 과정에서 붙게 된다.
  • 상수명은 대문자, 서로 다른 단어로 구성되어있을경우 _ 연결하는걸이 관례.
  • 상수는 구현 객체와 관련 없는 인터페이스 소속 멤버이므로 인터페이스로 바로 접근해서 상수값을 읽을 수 있다.

# 8.4 추상 메소드

  • 인터페이스는 구현 클래스가 재정의 해야 하는 public 추상 메소드 (abstract method) 를 멤버로 가질 수 있다.
  • 추상 메소드는 리턴 타입, 메소드명, 매개변수만 기술되고 중괄호 {} 를 붙이지 않는 메소드를 말한다.
  • public abstract를 생략하더라고 컴파일 과정에서 자동으로 붙게 된다.
  • 추상 메소드는 객체가 인터페이스를 통해 어떻게 메소드를 호출할 수 있는지 방법을 알려주는 역할을 한다.
  • 인터페이스 구현 객체는 추상 메소드의 실행부를 갖는 재정의된 메소드가 있어야 한다.

# 8.5 디폴트 메소드

  • 인터페이스에는 완전한 실행 코드를 가진 디폴트 메소드를 선언할 수 있다.
  • 추상 메소드는 실행부(중괄호{})가 없지만 디폴트 메소드는 실행부가 있다.

public default 리턴타입 메소드명(매개변수, ...) {}
  • 디폴트 메소드의 실행부에는 상수 필드를 읽거나 추상 메소드를 호출하는 코드를 작성할 수 있다.
  • 디폴트 메소드는 구현 객체가 필요한 메소드이다.
  • 구현 클래스는 디폴트 메소드를 재정의 해서 자신에게 맞게 수정할 수도 있다.
  • 재 정의시 반드시 public 접근제한자를 붙여야 하고, default 키워드를 생략해야 한다.

# 8.6 정적 메소드

  • 인터페이스에 정적 메소드 선언 가능
  • 추상메소드와 디폴트 메소드는 구현 객체가 필요하지만, 정적 메소드는 구현 객체가 없어도 인터페이스만으로 호출할 수 있다.
  • public 을 생략하더라고 자동으로 컴파일 과정에서 붙음

[public | private] static 리턴타입 메소드명(매개변수, ...) {...}
  • 인터페이스에 선언된 정적 메소드는 구현 객체 없이 인터페이스명으로 접근해서 호출할 수 있다.
  • 정적메소드의 실행부에는 상수 필드를 제외한 추상메소드, 디폴트 메소드, private 메소드 등을 호출할 수 없음. 이 메소드는 구현 객체가 필요한 인스턴스 메소드이기 때문이다.

# 8.7 private 메소드

  • 인터페이스의 상수 필드, 추상 메소드, 디폴트 메소드, 정적 메소드는 모두 public 접근 제한자를 갖는다.
  • 이 멤버들을 선언할 때에는 public 을 생략하더라도 컴파일 과정에서 public 접근 제한자가 붙어 항상 외부에서 사용이 가능하다.
  • 또한 인터페이스에 외부에서 접근할 수 없는 private 메소드 선언도 가능하다.
  • private 메소드는 디폴트 메소드 안에서만 호출이 가능한 반면, private 정적 메소드는 디폴트 메소드 뿐만 아니라 정적 메소드 안에서도 호출이 가능하다.
  • private 메소드의 용도는 디폴트와 정적 메소드들의 중복 코드를 줄이기 위함.
public interface Service {
    default void defaultMethod1(){
        system.out.println("1");
        defaultCommon();
    }
    default void defaultMethod2(){
        system.out.println("2");
        defaultCommon();
    }
    private void defaultCommon(){
        system.out.println("중복코드");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 8.8 다중 인터페이스 구현

  • 구현 객체는 여러개의 인터페이스를 implements 할 수 있다.
  • 인터페이스 A, 인터페이스 B 를 implements 뒤에 쉼표로 구분해서 작성해, 모든 인터페이스가 가진 추상 메소드를 재정의해야 한다.

public class 구현클래스명 implements 인터페이스A, 인터페이스B{
    // 모든 추상메소드 재정의
} 

# 8.9 인터페이스 상속

# 8.10 타입 변환

# 8.11 다형성

# 8.12 객체 타입 확인

# 8.13 봉인된 인터페이스