# 인터페이스 - 구현이 어떻든 깊이 학습할 필요없이 원하는 기능을 수행하고 결과 값을 제대로 받게 해주는 간편한 상호작용 기능 - 프레임워크의 내부 구성 학습 없이, 그저 지원해주는 메서드를 이용하여 간편하게 프로젝트를 개발할 수 있게 해준다 ## 일상 생활에서 인터페이스 - 문 손잡이: 문을 쉽게 열고 닫을 수 있게 해주는 인터페이스 - 전등 스위치: 조명을 켜고 끌 수 있게 해주는 인터페이스 - 자동차 대시보드: 차량의 속도, 연료 및 기타 중요한 데이터에 대한 정보를 표시하는 복잡한 인터페이스 - 스마트폰 화면: 터치 스크린은 다양한 앱과 기능에 액세스할 수 있는 직관적인 인터페이스 - 키보드/마우스: 컴퓨터와 상호작용을 하기 위한 인터페이스 - 텔레비전 리모콘: 채널을 변경하고 볼륨을 조절하고 텔레비전의 다른 기능을 제어할 수 있게 해주는 인터페이스 ## 자바에서의 인터페이스 ![](https://i.imgur.com/WdLvdAe.png) - 자바에서 클래스들이 구현해야하는 동작을 지정하는 용도로 사용되는 추상 자료형 - 자바에서 다중상속을 간접적으로 가능하게 해준다 - 자바에서는 기본적으로는 다중상속을 지원하지 않는다 - 인터페이스는 클래스와 별도로 구현 객체가 같은 동작을 한다는 것을 보장하기 위해 사용하는 것에 초점이 맞춰져있다. - 상속받은 인터페이스의 추상 메서드를 구현하지 않으면 컴파일 오류 발생 - 추상 클래스 상속과 전혀 다르지 않다 - 미구현으로 인한 컴파일 오류를 발생시켜 실수를 방지해준다 - 메서드 이름 오타 or 부모클래스의 메서드 이름만 바꾸고 자식 클래스는 손대지 않는 경우 - Java에서는 `@Override`라는 어노테이션을 제공한다 - 이 어노테이션을 메서드 위에 사용하면 상속받은 메서드를 구현하겠다는 의미 - 만약 부모 클래스에 같은 이름의 메서드가 없으면 오류 발생 - 인터페이스는 `public` 메서드만 가능 - 누구라도 보고 명령할 수 있는 동작 - 인터페이스는 다중 상속이 가능 (클래스 다중상속은 불가능) - 메서드가 중복되더라도 오버라이딩되지 않기 때문에 실체가 겹칠 위험이 없음 - 아무리 복잡하게 상속 구조를 해도 구현은 하나 뿐 - 인터페이스는 두 실체가 중복되어도 상속받은 클래스가 구현만 제공하면 됨 - 단 반환형만 다르면 컴파일 오류가 난다 - 두 함수를 다 구현할 방법이 없기 때문에 - 반환형만 다른 경우는 올바른 함수 오버로딩이 아님 - **인터페이스는 다중 상속의 해결법** > 인터페이스는 특수한 형태의 클래스다 > > - 어떤 상태도 없음 > - 동작의 구현도 없음 > - 동작의 시그내처만 있음 > - 이런 특징 때문에 클래스와는 약간 다른 규칙을 따른다 ### 인터페이스 문법 ![](https://i.imgur.com/jc9fZ1M.png) - 인터페이스를 작성하는 것은 추상 클래스를 작성하는 것과 같다고 보면 된다. (추상 메서드 집합) - `class` 대신 `interface`라는 키워드를 이용하여 선언할 수 있으며 메소드 시그니처와 상수 선언만을 포함할 수 있다 - 인터페이스의 모든 상수는 `public static final`이며, 모든 메서드는 `public abstract` 이다. - 인터페이스에 선언 시 편의상 생략이 가능하다. - `default` 키워드를 사용하여 구현부가 있는 메서드를 만들어줄 수 있다. - 구현체에게 수정 없이 광역으로 함수를 만들어주고 싶을 때 사용된다 - `default` 메서드가 다중 상속 문제로 인해 충돌 되는 경우 오버라이딩을 해야 한다 - 클래스가 인터페이스를 상속받을 때는 `implements` 키워드를 사용한다 - 인터페이스가 인터페이스를 상속받을 때는 `extends` 키워드를 사용한다 ### 인터페이스 정의 ```java public interface 인터페이스이름 { // 상수 public static final 타입 상수이름 = 값; 타입 상수이름 = 값; // public static final 생략 가능 // 메서드 public abstract 반환타입 메서드이름(매개변수목록); 반환타입 메서드이름(매개변수목록); // public abstract 생략 가능 // default 메서드 public default 반환타입 메서드이름(매개변수목록) { ... } 반환타입 메서드이름(매개변수목록) { ... } // public default 생략 가능 } ``` ```java public interface Car { // 상수 int WHEEL_COUNT = 4; // 메서드 void run(); // default 메서드 void stop() { System.out.println("차를 멈춤"); // Code to stop the car } } ``` ### 인터페이스 상속 (클래스가 인터페이스를 상속받을 때) ```java public class 클래스이름 implements 인터페이스이름 { // `implements` 키워드 사용하여 인터페이스 상속 // 인터페이스에 선언된 추상 메서드 구현 // 인터페이스에 선언된 default 메서드 재정의 } ``` ```java public class Sonata implements Car { @Override public void run() { System.out.println("소나타가 달립니다."); } @Override public void stop() { System.out.println("소나타가 멈춥니다."); } } ``` ### 인터페이스 상속 (인터페이스가 인터페이스를 상속받을 때) ```java public interface 인터페이스이름 extends 인터페이스이름 { // `extends` 키워드 사용하여 인터페이스 상속 // 인터페이스에 선언된 추상 메서드 구현 // 인터페이스에 선언된 default 메서드 재정의 } ``` ```java public interface HybridCar extends Car { // 인터페이스에 선언된 추상 메서드 구현 // 인터페이스에 선언된 default 메서드 재정의 } ``` ## 인터페이스는 다중 상속이 가능하다 - 자바에서 클래스는 다중상속이 되지 않는다. - 다중 상속은 잘못 사용할 경우 코드의 복잡도가 증가하고 가독성이 떨어지기 때문에 자바에서는 다중상속을 지원하지 않는다. - C++에서는 다중상속이 가능하다 - 인터페이스는 구현된 내용이 없기 때문에 다중 상속이 가능하다 - 인터페이스는 구현된 내용이 없고 구현되어야 할 메서드의 이름만 존재하기 때문에 다중 상속이 가능하다 ![](https://i.imgur.com/Mwb2dHz.png) ```java public class 클래스 이름 implements 인터페이스1, 인터페이스2, ... { // 인터페이스에 선언된 추상 메서드 구현 // 인터페이스에 선언된 default 메서드 재정의 } ``` ```java public interface Car { void run(); void stop(); } public interface ElectricCar { void charge(); } public class Sonata implements Car, ElectricCar { @Override public void run() { System.out.println("소나타가 달립니다."); } @Override public void stop() { System.out.println("소나타가 멈춥니다."); } @Override public void charge() { System.out.println("소나타가 충전됩니다."); } } ``` --- ![](https://i.imgur.com/55ILYaV.png) ```java public interface 인터페이스이름 extends 인터페이스1, 인터페이스2, ... { // `extends` 키워드 사용하여 인터페이스 상속 // 인터페이스에 선언된 추상 메서드 구현 // 인터페이스에 선언된 default 메서드 재정의 } ``` ```java public interface HybridCar extends Car, ElectricCar { // 인터페이스에 선언된 추상 메서드 구현 // 인터페이스에 선언된 default 메서드 재정의 } ``` ### 자바 버전별 인터페이스 기능 ![](https://i.imgur.com/3aozynW.png) - 자바 버전별로 인터페이스의 기능이 추가되었다 - 자바 8에서는 `default` 메서드와 `static` 메서드를 인터페이스에 추가할 수 있게 되었다 - `default` 메서드는 구현체에게 수정 없이 광역으로 함수를 만들어주고 싶을 때 사용된다 - `static` 메서드는 인터페이스의 메서드를 사용하기 위해 인스턴스를 생성할 필요가 없을 때 사용된다 - 자바 9에서는 `private` 메서드를 인터페이스에 추가할 수 있게 되었다 - `private` 메서드는 인터페이스 내부에서만 사용되는 메서드이다 - `default` 메서드를 구현할 때 사용되는 메서드이다 - `private` 메서드는 인터페이스를 구현하는 클래스에서는 사용할 수 없다 ### 컬렉션에서의 인터페이스 활용 예시 ![](https://i.imgur.com/unnp6Lz.png) # 추상클래스 vs 인터페이스 - 인터페이스나 추상클래스나 둘이 똑같이 추상 메소드를 통해 상속/구현을 통한 메소드 강제 구현 규칙을 가지는 추상화 클래스이다. - 다만 이 둘은 각각 고유의 몇몇 특징들을 가지고 있는데, 이러한 특징으로 인해 각각 사용처가 갈리게 된다. 또한 기능적인 부분 뿐만 아니라 인터페이스와 추상클래스가 내포하고있는 논리적인 의미로서도 사용처가 나뉜다. ## 추상클래스를 사용하는 경우 - 상속 받을 클래스들이 공통으로 가지는 메소드와 필드가 많아 **중복 멤버 통합**을 할때 - 멤버에 `public` 이외의 접근자(`protected`, `private`) 선언이 필요한 경우 - `non-static`, `non-final` 필드 선언이 필요한 경우 (각 인스턴스에서 상태 변경을 위한 메소드가 필요한 경우) - 요구사항과 함께 구현 세부 정보의 일부 기능만 지정했을 때 - 하위 클래스가 오버라이드하여 재정의하는 기능들을 공유하기 위한 상속 개념을 사용할 때 - 추상 클래스는 이를 상속할 각 객체들의 공통점을 찾아 추상화시켜 놓은 것으로, 상속 관계를 타고 올라갔을 때 같은 부모 클래스를 상속하며 부모 클래스가 가진 기능들을 구현해야할 경우 사용한다. ## 인터페이스를 사용하는 경우 - 어플리케이션의 기능을 정의해야 하지만 그 구현 방식이나 대상에 대해 추상화 할 때 - **서로 관련성이 없는 클래스**들을 묶어 주고 싶을때 (형제 관계) - **다중 상속**을 통한 추상화 설계를 해야할때 - 특정 데이터 타입의 행동을 명시하고 싶은데, 어디서 그 행동이 구현되는지는 신경쓰지 않는 경우 - 클래스와 별도로 **구현 객체가 같은 동작을 한다는 것을 보장**하기 위해 사용 ## 인터페이스 + 추상클래스를 사용하는 경우 ![](https://i.imgur.com/yFvpNQo.png) - 추상 클래스의 중복 멤버 통합과 인터페이스의 다중 상속 기능을 동시에 사용하기 위해서 종종 같이 사용되곤 한다 --- ### 구체클래스 vs 인터페이스 | 구체 클래스 | 인터페이스 | | -------------------------------- | --------------------------------- | | 상태와 동작을 모두 포함 | 동작에 대한 설명만 포함 | | 동작에 다양한 접근권한 부여 가능 | 모든 동작은 public | | 구체클래스로부터 개체 생성 가능 | 인터페이스로부터 개체 생성 불가능 | | 다중 상속의 부모가 될 수 없음 | 다중 상속의 부모가 될 수 있음 |