10-1. 인터페이스란?
인터페이스 (interface)
- 패키지에서 마우스 오른쪽 버튼 → [New] → [Interface]
- 모든 메서드가 추상 메서드로 선언됨 public abstract
- 모든 변수는 상수로 선언됨 public static final
interface 인터페이스 이름 { public static final float pi = 3.14F; public void makeSomething(); } |
- 자바8 부터 디폴트 메서드 (default method)와 정적 메서드(static method) 기능의 제공으로 일부 구현 코드가 있음
인터페이스 구현과 형 변환
- 인터페이스를 구현한 클래스는 인터페이스 형으로 선언한 변수로 형 변환 할 수 있음
Calc calc = new CompleteCalc();
- 상속에서의 형 변환과 동일한 의미
- 클래스 상속과 달리 구현 코드가 없으므로 여러 인터페이스를 구현할 수 있음 (cf.extends)
- 형 변환되는 경우 인터페이스에 선언된 메서드만을 사용가능함
10-2. 인터페이스와 다형성
- 하나의 인터페이스를 여러 객체가 구현하게 되면 클라이언트 프로그램은 인터페이스의 메서드를 활용하여 여러 객체의 구현을 사용할 수 있음 (다형성)
- 쉽게 풀어 말하면 인터페이스는 클라이언트 프로그램에 어떤 메서드를 제공하는지 미리 알려주는 명세 또는 약속의 역할
- 클라이언트 프로그램은 인터페이스에서 약속한 명세대로 구현한 클래스를 생성해서 사용
예제 시나리오
고객 센터에는 전화 상담을 하는 상담원들이 있습니다. 일단 고객 센터로 전화가 오면 대기열에 저장됩니다. 상담원이 지정되기 전까지 대기 상태가 됩니다. 각 전화를 상담원에게 배분하는 정책은 다음과 같이 여러 방식으로 구현할 수 있습니다. 1. 순서대로 배분하기 : 모든 상담원이 동일한 상담 건수를 처리하도록 들어오는 전화 순서대로 상담원에게 하나씩 배분합니다. 2. 짧은 대기열 찾아 배분하기 : 고객 대기 시간으 줄이기 위해 상담을 하지 않는 상담원이나 가장 짧은 대기열을 보유한 상담원에게 배분합니다. 3. 우선 순위에 따라 배분하기 : 고객 등급에 따라 등급이 노픈 고객의 전화르 우선 가져와서 업무 능력이 좋은 상담원에게 우선 배분합니다. |
Scheduler.java
먼저 상담원에게 전화 업무를 배분하는 기능을 구현하기 위해 Scheduler 인터페이스를 만든다.
Scheduler 인터페이스에는 시나리오 1~3에서 모두 공통으로 사용하는 메서드를 선언한다.ㅣ
getNextCall()은 다음 전화를 가져오는 기능
sendCallToAgent()는 상담원에게 전화를 배분하는 기능
package scheduler;
public interface Scheduler { //interface 파일 생성 public void getNextCall(); //다음 전화 가져오기 public void sendCallToAgent(); //상담원에게 전화 배분하기 } |
RoundRobin.java
package scheduler;
public class RoundRobin implements Scheduler { @Override public void getNextCall() { System.out.println("상담 전화를 순서대로 대기열에서 가져옵니다"); } @Override public void sendCallToAgent() { System.out.println("다음 순서 상담원에게 배분합니다"); } } |
LeastJob.java
package scheduler;
//현재 상담 업무가 없거나 상담 대기가 가장 적은 상담원에게 배분 public class LeastJOB implements Scheduler { @Override public void getNextCall() { System.out.println("상담 전화를 순서대로 대기열에서 가져옵니다"); } @Override public void sendCallToAgent() { System.out.println("현재 상담 업무가 없거나 대기가 가장 적은 상담원에게 할당합니다"); } } |
PriorityAllocation.java
package scheduler;
//고객 등급이 높은 고객의 전화부터 대기열에서 가져와 업무 능력이 높은 상담원 우선 배분 public class PriorityAllocation implements Scheduler { @Override public void getNextCall() { System.out.println("고객 등급이 높은 고객의 전화를 먼저 가져옵니다"); } @Override public void sendCallToAgent() { System.out.println("업무 skill 값이 높은 상담원에게 우선적으로 배분합니다"); } } |
SchedulerTest.java
package scheduler;
import java.io.IOException; public class SchedulerTest { public static void main(String[] args) throws IOException { System.out.println("전화 상담 할당 방식을 선택하세요."); System.out.println("R : 한명씩 차례로 할당"); System.out.println("L : 쉬고 있거나 대기가 가장 적은 상담원에게 할당"); System.out.println("P : 우선순위가 높은 고객 먼저 할당"); int ch = System.in.read(); //할당 방식을 입력받아 ch 변수에 대입 Scheduler scheduler = null; if(ch == 'R' || ch == 'r') { scheduler = new RoundRobin(); } else if(ch == 'L' || ch == 'l') { scheduler = new LeastJOB(); } else if(ch == 'P' || ch == 'p') { scheduler = new PriorityAllocation(); } else { System.out.println("지원되지 않는 기능입니다."); return; } scheduler.getNextCall(); scheduler.sendCallToAgent(); } } |
출력
![]() |
![]() |
클라이언트가 클래스를 사용하는 방법
추가로 만들어야 하는 배분 정책은 Scheduler 인터페이스를 구현하는 새 클래스로 만들면 된다.
어떤 클래스를 구현하건 클라이언트가 인터페이스를 구현한 클래스를 사용하는 방식은 다음 코드와 같다.
scheduler.getNextCall( ); scheduler.sendCallToAgent( ); |
이렇게 클라이언트 프로그램은 각 클래스의 구현 방법을 몰라도 인터페이스에서 선언된 매개변수, 반환 값을 보고 클래스를 사용할 수 있다.
인터페이스는 구현된 클래스를 사용하는 클라이언트 코드와 기능을 제공하는 코드 사이의 약속이다.
10-3. 인터페이스의 여러가지 요소
상수
- 모든 변수는 상수로 변환 됨 public static final
double PI = 3.14; int ERROR = -9999999; |
추상 메서드
- 모든 선언된 메서드는 추상 메서드 public abstract
디폴트 메서드 (자바8 이후)
- 구현을 가지는 메서드, 인터페이스를 구현하는 클래스들에서 공통으로 사용할 수 있는 기본 메서드
- default 키워드 사용
- 구현 하는 클래스에서 재정의 할 수 있음
- 인터페이스를 구현한 클래스의 인스턴스가 생성 되어야 사용 가능함
정적 메서드 (자바8 이후)
- 인스턴스 생성과 상관 없이 인터페이스 타입으로 사용할 수 있는 메서드
- static
private 메서드 (자바9 이후)
- 인터페이스를 구현한 클래스에서 사용하거나 재정의 할 수 없음
- 인터페이스 내부에서만 사용하기 위해 구현하는 메서드
- default 메서드나 static 메서드에서 사용함
10-4. 인터페이스 활용하기
여러 인터페이스 구현
- 자바의 인터페이스는 구현 코드가 없으므로 하나의 클래스가 여러 인터페이스는 구현 할 수 있음
- 디폴트 메서드가 중복 되는 경우는 구현 하는 클래스에서 재정의 하여야 함
- 여러 인터페이스를 구현한 클래스는 인터페이스 타입으로 형 변환 되는 경우 해당 인터페이스에 선언된 메서드만 사용 가능
인터페이스의 상속
- 인터페이스 사이에도 상속을 사용할 수 있음
- extends 키워드를 사용
- 인터페이스는 다중 상속이 가능하고 구현 코드의 상속이 아니므로 타입 상속 이라고 함
클래스 상속과 인터페이스 구현 함께 쓰기
- 실무에서 프레임워크나 오픈소스와 함께 연동되는 구현을 하게 되면 클래스 상속과 인터페이스의 구현을 같이 사용한는 경우가 많음
예제 시나리오
BookShelf(책장) 클래스는 책을 넣은 순서대로 꺼내어 볼 수 있도록 만들려고 합니다. (처음 들어간 자료부터 꺼내어 쓰는 것을 큐queue 자료 구조라고 한다. 선착순 모집 같은 것.) |
Shelf.java
package bookshelf;
import java.util.ArrayList; public class Shelf { protected ArrayList<String> shelf; //자료를 순서대로 저장할 ArrayList 선언 public Shelf() { shelf = new ArrayList<String>(); //디폴트 생성자로 Shelf 클래스를 생성하면 ArrayList도 생성됨 } public ArrayList<String> getShelf() { //저장되어있는 배열 shelf를 반환 return shelf; } public int getCount() { //배열 shelf에 저장된 요소 개수를 반환 return shelf.size(); } } |
Queue.java
package bookshelf;
public interface Queue { void enQueue(String title); //배열의 맨 마지막에 추가 String deQueue(); //배열의 맨 처음 항목 반환 int getSize(); //현재 Queue에 있는 개수 반환 } |
BookShelf.java
package bookshelf;
public class BookShelf extends Shelf implements queue { @Override public void enQueue(String title) { shelf.add(title); //배열에 요소 추가 } @Override public String deQueue() { return shelf.remove(0); } @Override public int getSize() { return getCount(); //배열 요소 개수 반환 } } |
BookShelfTest.java
package bookshelf;
public class BookShelfTest { public static void main(String[] args) { queue shelfQueue = new BookShelf(); shelfQueue.enQueue("태백산맥 1"); shelfQueue.enQueue("태백산맥 2"); //순서대로 요소 추가 shelfQueue.enQueue("태백산맥 3"); System.out.println(shelfQueue.deQueue()); System.out.println(shelfQueue.deQueue()); //입력 순서대로 요소를 꺼내서 출력 System.out.println(shelfQueue.deQueue()); } } |
출력
태백산맥 1
태백산맥 2 태백산맥 3 |
'Programming Language > JAVA' 카테고리의 다른 글
기본 이론(1) (0) | 2023.05.28 |
---|---|
인터페이스(interface) (0) | 2023.05.25 |
[Do it 자바 프로그래밍 입문] 09.추상 클래스 (0) | 2023.05.24 |
[Do it 자바 프로그래밍 입문] 08.상속과 다형성 (1) | 2023.05.23 |
아리송한 개념들 짜집기 모음 (0) | 2023.05.22 |