인터페이스는 객체의 사용 방법을 정의한 타입이다. 인터페이스는 객체의 교환성을 높여주기 때문에 다형성을 구현하는데 매우 중요하다.
인터페이스는 코드와 객체가 서로 통신하는 접점 역할을 한다. 코드가 인터페이스의 메소드를 호출하면 인터페이스는 객체의 메소드를 호출시킨다. 그리고 객체가 반환한 데이터를 인터페이스가 코드에 반환한다.
인터페이스를 사용하는 이유는 개발 코드를 수정하지 않고, 사용하는 객체를 변경할 수 있도록 하기 위해서이다.
인터페이스는 하나의 객체가 아니라ㅏ 여러 객체들과 사용이 가능하기 때문에 어떤 객체를 사용하느냐에 따라 실행 내용과 리턴값이 달라질 수 있다. 따라서 코드 변경없이 실행 내용과 리턴값을 다양화 할 수 있다.
인터페이스 선언은 class 대신에 interface라고 적으면 된다. ~.class 형태로 컴파일되기 때문에 물리적 형태는 클래스와 동일하다.
인터페이스는 객체로 생성할 수 없기 때문에 생성자를 가질 수 없고, 객체 사용 설명서이기 때문에 런타임 시 데이터를 저장할 수 있는 필드를 선언할 수 없다. 상수 필드와 메소드만 구성 멤버로 가진다.
상수를 대입할 때에는 반드시 초기값을 대입해야 한다. 근데 인터페이스에서는 굳이 상수라고 표시하기 위해 public static final을 붙일 필요는 없다. 인터페이스에서는 컴파일 시 자동으로 붙게 된다.
public interface InterfaceName {
public int ABC_DEF = 0; // 초기값을 설정해야 한다.
}
또한 인터페이스에 선언된 추상 메소드는 모두 public abstract가 자동으로 붙게 된다. 추상메소드는 중괄호 {}가 붙지 않은 메소드이다.
public interface InterfaceName {
[public abstract] void methodA(); // 중괄호 {} 가 없는 추상메소드
}
인터페이스의 default 메소드는 public 특성을 갖기 때문에 default만 붙여주면 public은 자동으로 붙게 된다. default 메소드는 인터페이스에 선언되지만 사실은 구현 객체가 가지고 있는 인스턴스 메소드라고 생각해야 한다.
public interface InterfaceName {
[public] default void methodB(){
.... // 실행 내용
}
}
인터페이스의 정적(static) 메소드 또한 public이 자동으로 붙기 때문에 static만 붙여줘도 된다. 정적 멤버는 static이 붙은 필드나 메소드로, 객체에 속해 있는게 아니라 클래스에 속해있는 것이기 때문에 객체를 생성하지 않고도 호출 할 수 있는 멤버들이다.
public interface InterfaceName {
[public] static void methodC() {
// 실행 내용
}
}
인터페이스 구현
코드가 인터페이스 메소드를 호출하면 인터페이스는 객체의 메소드를 호출한다. 객체는 인터페이스에서 정의된 추상메소드와 동일한 이름, 매개 타입, 리턴 타입을 가진 실체 메소드를 가지고 있어야 한다.
public class ClassName implements InterfaceName {
// 인터페이스에 선언된 메소드와 같은 메소드가 선언 되어야 한다.
}
인터페이스 사용 방법은 다음과 같다.
public class Main {
public static void main(String[] args) {
InterfaceName inter = new ClassName();
}
}
익명 구현 객체
일회성의 구현 객체를 만들기 위해 소스 파일을 만들고 클래스를 선언하는 것은 비효율적이다. 자바는 소스 파일을 만들지 않고 구현 객체를 만들수 있는데 그것이 익명 구현 객체이다.
InterfaceName 변수 = new InterfaceName() {
// 인터페이스에 선언된 추상메소드를 실체화하는 똑같은 메소드를 선언한다.
};
하나의 실행문이기 때문에 반드시 마지막에 세미콜론 ; 을 붙여야 한다.
인터페이스를 중괄호 {} 안에서 구현해서 클래스로 만들고 그렇게 만들어진 클래스를 new를 통해서 객체로 만드는 것이다. 인터페이스의 모든 추상 메소드를 중괄호 {} 안에서 실체 메소드로 만들어야한다. 추가적인 필드와 메소드를 선언할 수 있지만 변수를 통해서 접근 할 수는 없다.
다중 인터페이스 구현 클래스
클래스는 여러 개의 인터페이스를 사용할 수 있다. 대신, 모든 인터페이스의 추상 메소드를 구현 해야하고, 그렇지 않다면 그 클래스는 추상 클래스로 선언해야 한다.
public class ClassName implements InterfaceA, InterfaceB {
// InterfaceA와 InterfaceB 추상 메소드를 구현해야 한다.
}
인터페이스 사용
인터페이스를 사용하려면 인터페이스 변수를 선언하고 그 변수에 구현 객체를 대입하는 것이다.
public class Main {
// 인터페이스 변수
InterfaceName inter;
inter = new ClassA();
inter.method1(); // Interface의 추상메소드를 구현한 ClassA 객체의 메소드
inter.method2();
inter = new ClassB();
inter.method1();
inter.method2();
}
default 메소드 사용
디폴트 메소드는 인터페이스에서 선언되긴 하지만, 인터페이스에서 바로 사용할 수 없다. 디폴트 메소드는 인스턴스 메소드라서 구현 객체가 있어야 한다. 근데 굳이 인터페이스를 구현하는 클래스에서 선언하지 않아도 된다. 그리고 오버라이딩해서 사용할 수도 있다.
InterfaceName inter = new ClassA();
inter.method3();
// method3이 인터페이스의 디폴트 메소드라면 ClassA 객체가 직접 가지고 있지 않아도 사용 가능하다.
// ClassA 객체에서 오버라이딩해서 필요한 형태로 바꿔서 사용할 수도 있다.
정적(static) 메소드 사용
인터페이스의 정적 메소드는 인터페이스를 통해 바로 호출이 가능하다.
InterfaceName.method4();
// method4 가 정적 메소드라면,
// 객체를 참조하는 변수를 통해서 메소드를 호출하는게 아니라 인터페이스를 통해서 바로 메소드를 호출할 수 있다.