인터페이스
- 상호작용을 할 수 있는 경계 또는 접점
- 서로 다른 장치나 시스템을 연결하고 소통할 수 있도록 하는 표준화된 규격이나 방법
- 완벽히 추상회된 설계도
- 클래스와 유사하게 작성되지만, class 대신
interface 키워드 사용
- 인터페이스 내에 선언된 메서드는 public abstract가 기본으로 생략.
- 인터페이스 내에 정의된 변수는 자동으로 public static final로 간주
(설계도 자체에 들어있는 것으로, 변수가 아니다.)
public interface 인터페이스이름{
[public static final] 타입 상수이름1 = 10;
타입 상수이름2 = 10;
public abstract 반환형 메서드이름(매개변수들);
반환형 메서드이름2(매개변수들_);
}
- 인터페이스의 모든 변수는 사실 상수를 선언하는 것이다.
- 인터페이스는 그 자체로 객체 생성이 안 되므로, 반드시 일반 클래스에 의해 구현되어야 한다.
- public class MyClass `implements` MyInterface { }
- 인터페이스에 있는 메서드를 모두 구현해줘야 한다.
- 객체 생성을 위해서는, 인터페이스를 구현하는 클래스를 만들어 이를 통해 객체 생성
- 클래스는 여러 개의 인터페이스를 다중 구현 가능
- public class MyClass
implements MyInterface, interfaceA, interfaceB { }
- 클래스는 인터페이스의 추상 메서드를 모두 구현(재정의)해야 객체 생성 가능.
- 모두 재정의하지 않을 경우 추상 메서드로 남기는 것도 가능하다.
- 인터페이스를 구현한 클래스로 만든 객체는 해당 인터페이스 타입으로 참조할 수 있다.
- 동작 바인딩 : 런타임 시점에는 실제 객체의 메서드가 호출
- 해당 인터페이스를 구현한 클래스로 만든 객체를, 해당 인터페이스로 참조할 수 있다.
public interface AlarmSound {
// 인터페이스를 구현한 객체는 반드시 해당 기능이 있다는 것을 보장한다.
void alarm();
}
public class GalaxyPhone implements AlarmSound {
// 메서드 기능 강제
@Override
public void alarm() {
System.out.println("Ding Ding Ding");
}
}
public class Iphone implements AlarmSound {
@Override
public void alarm() {
System.out.println("Beep Beep Beep");
}
}
public class Test {
public static void main(String[] args) {
AlarmSound galaxy = new GalaxyPhone();
AlarmSound iphone = new Iphone();
galaxy.alarm();
iphone.alarm();
// 배열로 생성 또한 가능
AlarmSound[] phones = {new GalaxyPhone(), new Iphone()};
for (AlarmSound sound : phones) {
sound.alarm();
}
}
}
- 인터 페이스로 참조하면, 해당 인터페이스에 정의되어 있는 내용만 보인다.
- 별도로 사용하고 싶다면 GalaxyPhone 으로 참조를 해야 한다.
인터페이스의 상속

- extends 키워드를 이용하여 상속, 클래스와 달리 다중 상속이 가능하다.
- 추후에 class 가 implements를 받게 되면, 상속 받은 인터페이스 모두 정의 후 사용해야 한다.
public class Animal implements Eatable, Speakable {
@Override
public void speak() {
}
@Override
public void eat() {
}
}
public interface AnimalBehavior extends Eatable, Speakable{
}
public class Animal implements AnimalBehavior {
@Override
public void speak() {
}
@Override
public void eat() {
}
}
- 다중 상속 : 추상 메서드를 물려 받는다.
- 인터페이스의 다중 상속 시, 메서드 명이나 반환형 메서드(매개변수) 가 겹치더라도 구현 클래스에서 정의하여 사용하기 때문에 상관이 없다.
- 클래스가 인터페이스를 구현하는 시점에 메서드 내용을 정의하면 된다.
- 변수의 경우 상수(static)으로 정의하기 때문에,
클래스이름.변수명으로 접근해야 한다.
인터페이스 메서드
default method
- 인터페이스의 하위 호환성을 유지하면서 새로운 메서드를 추가한다.
- 인터페이스에 구현부가 있는 메서드를 작성하기 위해서.
- 메서드 앞에 default 라는 키워드와 함께 public 접근 제한자 사용.
- public 은 생략이 가능하다.
- 클래서에서 인터페이스의 default 메서드를 재정의할 수 있다.
public interface My{
void abstractMethod();
default void deFaultMethod(){
System.out.println("this is a default method.");
}
}
- 메서드를 별도로 인터페이스에 추가해주는 경우, 해당 방식을 사용하기도 한다.
static method
- 인터페이스에서 선언된 static 메서드는 클래스의 static 메서드와 사용 방법이 동일
- 인터페이스명.method명 으로 사용
- static 메서드는 인터페이스를 구현한 클래스에서 상속되거나 재정의 할 수 없다.
public interface My{
void abstractMethod();
static void staticMethod(){
System.out.println("this is a static method.");
}
}
<사용 방법>
public class MyClass implements MyInterface {
public static void main(String[] args) {
MyClass m = new MyClass();
m.method1();
MyInterface.method4();
}
}
- default 메서드끼리 겹친다면
- A implements B, C {}
- B와 C의 동일한 이름을 가진 default 메서드가 있다면, 구현 클래스에서 오버라이드
- A의 클래스에서 오버라이드 하는 경우, B 혹은 C에서 선택하거나 완전히 다른 메서드로 재정의 할 수 있다.
- default 메서드와 상위 메서드가 겹치는 경우
- A extends B implements C
- B의 메서드와 C의 default 메서드가 겹칠 때
- 기본적으로 B의 메서드를 사용하며, 재정의는 가능하다.
인터페이스 필요성
- 표준화 처리 가능 : 여러 클래스들이 동일한 인터페이스를 구현하여 일관된 방식으로 동작 처리
- 개발 기간 단축 가능 : 시스템 구조를 먼저 설계하고, 각 부분을 독립적으로 개발하여 개발 기간 단축
- 서로 관계가 없는 클래스들 간의 관계 형성
- 간접적인 클래스 사용으로 모듈 교체 용이
- 독립적인 프로그래밍 가능 : 각 클래스가 독립적으로 개발 및 테스트 가능, 코드 재사용성과 유지보수성 향상
- 다형성 지원
- 설계의 유연성 제공 : 클래스간의 강합 결합을 피해 유연성 증가, 시스템 변경 및 확장의 영향 최소화
추상화
- 불필요한 세부사항을 숨기고, 중요한 특징이나 기능에 집중 ( 인터페이스 사용 목적)
- 공통의 인터페이스를 정의하고, 구체적 구현은 하위 클래스에 맡긴다.
- 추상화된 클래스 (상위 클래스, 추상 클래스, 인터페이스)에 의존, 연관된 코드 작성 → 체계의 재조직
- SW 목적에 맞는 특징, 행위만 추출 / 추상적 객체를 정의하는 기능
- 객체지향 프로그래밍에서, 추상화 선언되었을 경우
- 그 자체로 객체 생성 불가를 의미하며, 객체 생성을 위해서는 프로그래머에게 구현을 강제하는 책임이 있음을 의미
Class vs Interface

Abstract Class vs Interface
