인터페이스

Jan 28, 2024
인터페이스

1. 인터페이스란?

inter 교차로 / face 직면하다 내가 할 수 있는게 제한되어 있구나. 하고 받아들이면 됨. 직면하면 3가지 길만 제시해줌. 그 3가지 길 외에는 못가게 하는게 바로 인터페이스
notion image
 

2. 인터페이스의 특징

1. 인터페이스는 추상 메소드를 가진다. (추상 메소드에서 abstract를 생략 가능) >> 추상메소드만 가진다. 구체화된 메소드는 xxx 그래서 람다식을 사용하는 것! >> 아래의 4-3. 구현체란? 참조 2. extends가 아니라 implements 사용 > 메소드를 강제시킴 3. 인터페이스는 추상화가 아니라 메소드의 강제이다 > 동적 바인딩 4. 다형성 가능하다. 5. 인터페이스는 생성자를 가질 수 없다. (new가 안되니까) 인터페이스는 인스턴스화될 수 없기 때문에 생성자가 필요하지 않다. (대신 인터페이스를 구현하는 클래스에서 생성자를 정의하고 사용) 6. 인터페이스에서 받아온 메소드(구현 메소드)는 반드시 public으로 구현해야 한다. (인터페이스 메소드는 기본적으로 public이므로 구현할 때, 메소드의 가시성을 줄여서는 안됨)
 

3. 인터페이스와 프로토콜의 차이

둘 다 약속이라는 점은 같다. 다만, · 프로토콜 = 수평적 ex) 여기 돈 백만원 놔둘테니까 둘이서 알아서 가져가 > a : 새벽 4시에 돈 가지러 갈거니까 b 너도 새벽 4시에 와! b : ㅡㅡ... b는 올까? ㄴㄴ > 협의 하겠지(이런 협의점을 찾는게 프로토콜) · 인터페이스 = 수직적 (일방적으로 약속을 결정, 갑·을 관계) ex) a : b야, 내가 너 돈 천만원 줄게. 돈 받으려면 새벽 4시에 와 ㅋㅋ b : 웅!! ㅎㅎ b는 거절하지 않는다. 이게 바로 인터페이스
ex. 배달의 민족 처음에 출시했을 때는 배민이 돌아다니면서 저희 앱에 음식점 등록해주세요 ㅠㅠ(프로토콜) 하고 다니지만, 시간이 지나면서 업체 사장님들이 먼저 배민에 등록하게 해주세요ㅠㅠ (인터페이스) 하는 것.
 
추가 그림 설명
notion image
  • 우리 컨테이너에 맞는 트럭을 만들어줘 > 트럭회사 : 싫은뎅 내 이익이 머임?! > 프로토콜
  • 모든 트럭이 컨테이너의 규격에 맞춰서 만들어져서 나옴 > 컨테이너가 인터페이스
 

4. 인터페이스와 추상클래스의 차이

4-1. 추상클래스
* 추상클래스의 만드는 시점 : 아래에서 위로 코딩을 하다가 '이렇게 만들면 추상클래스로 만들 수 있겠는데?' 라는 시점에서 공통적인 것들을 뽑아올리면서 만들어줌. * a 메소드는 쓰고 b 메소드는 안 씀 > 공통적으로 사용 안 함 > 못 끌어올림 (추상화 x) * 공통적인 4가지(ex, 모든 애들이 hp가 있음, 매직 쉴드 사용함) > 추상화 가능
💡
반드시 추상클래스로 만들어야 하는 게 아니다. 그냥 클래스로도 가능! 다만, 추상클래스의 특징 2가지 (new 불가, 자식 클래스에서 메소드 구현 강제) 추상클래스의 특징 2가지를 쓸 경우에 > 추상클래스
notion image
 
4-2. 인터페이스
* 인터페이스 만드는 시점 : 위에서 아래로 애네들(구현체)한테 이 메소드가 무조건 필요한데!!!!!! 이 메소드는 무조건 구현해야해!!! 하고 강제시키는 것 > 인터페이스 > 그럼 그 메소드를 무조건 만들게 됨. **강제화 시켜야지** 내가 설계한 프로그램이 돌아가기 때문에 인터페이스를 함. 왜냐? 동적바인딩 하려고! 메서드 이름을 똑같이 만들어야지만 내가 설계한 규칙대로 가는 것
notion image
 
4-3. 구현체란?
💡
구현체 : 인터페이스를 구현한 실제 클래스 (인터페이스를 상속 받은 자식 클래스가 해당 인터페이스의 구현체)
💡
인터페이스를 ‘객체화’ 시켜서 매개변수로 받고 싶다. (Dragoon d1 = new Dragoon(new interfaceClass) 처럼) 하지만 인터페이스는 new가 불가능하고, 추상 메소드만 가질 수 있으므로 객체화 시키려면 인터페이스를 implements 하는 새로운 클래스를 만들고, 그 클래스 내부에서 action() 메소드를 구체화시켜야 한다. 그러면 너무! 번거롭고 쓸데없는 클래스가 늘어난다. 그걸 방지하기 위해서 나온게 바로 람다식
 
인터페이스의 다중 상속
notion image
notion image
 
💡
인터페이스랑 추상 클래스는 문법적으로는 똑같음. 단, 인터페이스는 다중 상속을 지원한다. (상속은 다중상속 x)
💡
인터페이스 : 오브젝트 아님. new 못함. 메소드를 강제하는 것.
 

5. 인터페이스 예제

초기 코드
package ex07.example; interface Remocon { void on(); //(=public abstract void on(); 같은 말) 추상메소드니까 (); void off(); //(=public abstract void off(); 같은 말) } class SamsungRemocon implements Remocon { @Override public void on() { } @Override public void off() { } } class LgRemocon implements Remocon { @Override public void on() { } @Override public void off() { } } public class InterEx01 { public static void main(String[] args) { } }
Remocon에 대한 구현체를 만들어준다. 삼성리모콘과 LG리모콘은 on, off라는 기능을 꼭!! 넣어야하니까 위에서 아래로 > 인터페이스. ex) 삼성만 리모콘 메소드 이름이 cute, pretty 이런거면 곤란... 인터페이스로 강제하자.
 

 
<Remocon 인터페이스 직접 구현 불가> → 다형성을 이용하자
package ex07.example; interface Remocon { void on(); void off(); } class SamsungRemocon implements Remocon { @Override public void on() { System.out.println("삼성 리모컨 on"); } @Override public void off() { System.out.println("삼성 리모컨 off"); } } class LgRemocon implements Remocon { @Override public void on() { System.out.println("엘지 리모컨 on"); } @Override public void off() { System.out.println("엘지 리모컨 off"); } } public class InterEx01 { public static void main(String[] args) { Remocon samsung = new SamsungRemocon(); samsung.on(); } }
notion image
💡
* Remocon r = new Remocon(); 는 불가능!! Remocon은 인터페이스이기 때문에 직접 인스턴스를 생성할 수 없다. new로 뜰 수 있는 SamsungRemocon클래스의 인스턴스를 생성하여 Remocon타입의 변수에 할당한다. (SamsungRemocon클래스는 Remocon 인터페이스를 구현하고 있어서 가능) (상속처럼 heap에 [Remocon, SamsungRemocon] 이 붙어서 뜬다. - 인터페이스 다형성)
 
Remocon 라이브러리 ★
interface Remocon 부분을 라이브러리라고 치자
해당 코드는 보이지 않는다.
class SamsungRemocon implements Remocon { @Override public void on() { System.out.println("삼성 리모컨 on"); } @Override public void off() { System.out.println("삼성 리모컨 off"); } } class LgRemocon implements Remocon { @Override public void on() { System.out.println("엘지 리모컨 on"); } @Override public void off() { System.out.println("엘지 리모컨 off"); } }
 

 
<라이브러리를 만드는 건 아직x 지금은 그냥 설명을 보고 사용할 수 있어야 한다.>
notion image
/ Remocon의 자식 중에 SamsungRemocon, LgRemocon가 있다는 말.
 

 
package ex07.example; interface Remocon { void on(); void off(); } /** * <설명란> * 작성자 : 홍길동 * 날짜 : 2023.12.26 * 구현체 : SamsungRemocon, LgRemocon //이게 무조건 적혀있어야 사용할 수 있음. * //구현체가 뭔지 안 적혀있으면 쓰레기다! */ class CommonRemocon { // [Remocon <-, SamsungRemocon] // [Remocon <-, LgRemocon] private Remocon r; //new가 안되어서 인터페이스 or 추상클래스라고 추측가능 public CommonRemocon(Remocon r) { this.r = r; } public void on() { r.on(); } public void off() { r.off(); } } public class InterEx01 { public static void main(String[] args) { CommonRemocon cr = new CommonRemocon(new SamsungRemocon()); cr.on(); } }
💡
new CommonRemocon(new SamsungRemocon())" 코드는 CommonRemocon 객체를 생성하면서 생성자에 SamsungRemocon 객체를 전달하는 코드입니다. 이로써 CommonRemocon은 Remocon 인터페이스의 메서드를 호출할 수 있는 SamsungRemocon 객체를 내부적으로 가지게 됩니다. 즉, 다형성을 위함!
 

 
notion image
* CommonRemocon 클래스를 하나 만들고, 생성자를 전달 받는다. * CommonRemocon 클래스는 Remocon 인터페이스를 구현한 클래스들을 다루기 위한 일반적인 리모컨 기능을 제공하는 클래스 이 클래스의 생성자인 "public CommonRemocon(Remocon r)" 메서드는 Remocon 타입의 파라미터를 받아서 해당 파라미터를 인스턴스 변수 r에 할당. 이렇게 함으로써 CommonRemocon 클래스의 메서드인 on()과 off()에서는 인스턴스 변수 r에 저장된 Remocon 구현체의 메서드를 호출할 수 있다.
💡
private Remocon r; 은 CommonRemocon 클래스에서 Remocon 구현체의 인스턴스를 저장하기 위한 변수로 사용
notion image
 

 
notion image
 
notion image
객체로 Remocon을 받으려고 보니까, 에러가 발생! > 오브젝트가 아니라 new를 못하는구나! 인터페이스나 추상클래스라고 추정할 수 있다.
 
notion image
그래서 구현체(자식클래스)인 SamsungRemocon() 클래스를 객체로 받았다.
💡
CommonRemocon cr = new CommonRemocon(new SamsungRemocon()); 와 Remocon cr1 = new SamsungRemocon(); 는 둘 다 같은 객체를 생성하는 코드. * 변수의 타입과 객체를 참조하는 방식이 약간 다를 뿐 문법상으로는 같은 코드
 

 
<CommonRemocon cr = new CommonRemocon(new SamsungRemocon());>
💡
CommonRemocon 클래스의 생성자에 SamsungRemocon 객체 (new SamsungRemocon())를 인자로 전달하여 CommonRemocon 객체를 초기화 함 > 이렇게 함으로써 CommonRemocon 객체는 SamsungRemocon 객체를 사용하여 동작 > 변수 cr은 CommonRemocon 클래스의 객체를 참조
 
<Remocon cr1 = new SamsungRemocon();>
💡
Remocon은 인터페이스 이름. 이 코드는 Remocon 인터페이스를 구현한 SamsungRemocon 클래스의 객체를 생성하는 것을 의미한다. SamsungRemocon 클래스의 객체를 생성하여 변수 cr1에 할당한다. 변수 cr1은 Remocon 인터페이스를 구현한 SamsungRemocon 객체를 참조
 
💡
즉, 두 코드는 모두 SamsungRemocon 객체를 생성하여 사용하는 것. 다만, 첫 번째 코드는 CommonRemocon 클래스를 사용하여 객체를 생성하고 초기화하며, 두 번째 코드는 Remocon 인터페이스를 사용하여 SamsungRemocon 객체를 참조한다.
💡
동적라이딩이 되어서 (new SamsungRemocon())을 넣으면 Remocon r의 메소드가 실행 즉, 삼성리모컨 on이나 삼성리모컨 off가 실행
 
최종 코드
package ex07.example; interface Remocon { void on(); void off(); } class SamsungRemocon implements Remocon { @Override public void on() { System.out.println("삼성 리모컨 on"); } @Override public void off() { System.out.println("삼성 리모컨 off"); } } class LgRemocon implements Remocon { @Override public void on() { System.out.println("엘지 리모컨 on"); } @Override public void off() { System.out.println("엘지 리모컨 off"); } } /** * 작성자 : 홍길동 * 날짜 : 2023.12.26 * 구현체 : SamsungRemocon, LgRemocon //이게 무조건 적혀있어야 사용할 수 있음. */ class CommonRemocon { // [Remocon <- SansumgRemocon] // [Remocon <- LgRemocon] private Remocon r; //new가 안되어서 인터페이스 or 추상클래스라고 추측가능 public CommonRemocon(Remocon r) { this.r = r; } public void on() { r.on(); //삼성리모콘 클래스.메소드명 } public void off() { r.off(); } } public class InterEx01 { public static void main(String[] args) { CommonRemocon cr = new CommonRemocon(new SamsungRemocon()); cr.on(); } }
notion image
 
+) 주호 리모컨
package ex07.example; class SamsungRemocon implements Remocon { @Override public void on() { System.out.println("삼성 리모컨 on"); } @Override public void off() { System.out.println("삼성 리모컨 off"); } } class LgRemocon implements Remocon { @Override public void on() { System.out.println("엘지 리모컨 on"); } @Override public void off() { System.out.println("엘지 리모컨 off"); } } interface Remocon { void on(); void off(); } /** * 작성자 : 홍길동 * 날짜 : 2023.12.26 * 구현체 : SamsungRemocon, LgRemocon */ class CommonRemocon { // [Remocon <-, SamsungRemocon] // [Remocon <-, LgRemocon] private Remocon r; // 인터페이스 or 추상클래스 public CommonRemocon(Remocon r) { this.r = r; } public void on() { r.on(); // [Remocon <-, SamsungRemocon] } public void off() { r.off(); } } class JoohoRemocon implements Remocon { @Override public void on() { System.out.println("주호 리모콘 on"); } @Override public void off() { System.out.println("주호 리모콘 off"); } } public class InterEx01 { public static void main(String[] args) { CommonRemocon cr = new CommonRemocon(new JoohoRemocon()); cr.off(); } }
동적 바인딩이라! new JoohoRemocon() 클래스를 인스턴스화 시켜서 생성자에 넣으면 cr.off()를 해서 주호 리모콘 off가 나온다!
💡
주호 리모콘은 삼성, 엘지 리모컨처럼 라이브러리에서 제공된 클래스가 아니다. CommonRemocon에서 사용하려면 일단 new할 클래스가 만들어져 있어야 하니, 삼성, 엘지 리모컨 클래스처럼 @Override해서 클래스를 만들어 놓고 사용한다.
 

 
CommonRemocon와 Remocon은 has의 관계 > 컴포지션이라고 부름. 결합
CommonRemocon은 리모컨을 사용하는 클래스이며, Remocon은 인터페이스로 리모컨의 기능을 정의한 것
CommonRemocon이 자동차를 나타내는 클래스이고, Remocon r은 자동차의 핵심 부품인 엔진을 나타내는 변수
notion image
notion image
💡
CommonRemocon 클래스의 start() 메서드를 호출해도, Remocon r 변수에 저장된 엔진 객체의 start() 메서드가 실행된다는 말은 = 동적라이딩
 
💡
구현체 = 인터페이스를 구현 받은 ‘자식 클래스’
 
Share article

codingb