티스토리 뷰
출처 : DO IT! 자바프로그래밍 (저 : 박은종)
INTERFACE 인터페이스
- 인터페이스란
- 인터페이스와 다형성
- 인터페이스 요소 살펴보기
- 인터페이스 활용하기
- 인터페이스란
인터페이스는 구현 코드가 없다. 추상 메서드와 상수로만 이루어져 있다.
이러한 인터페이스는 클래스 혹은 프로그램이 제공하는 기능을 명시적으로 선언하는 역할을 한다.
- implements
: 인터페이스에서는 인터페이스에 선언한 기능을 클래스가 구현한다는 의미로 implements 예약어를 사용
구현하는 클래스에서는 인터페이스에 선언된 추상메서드를 구현한다.
package Interface;
public interface Calc {
double PI = 3.14;
int ERROR = -99999999;
int add(int num1, int num2);
int substract(int num1, int num2);
int times(int num1, int num2);
int divide(int num1, int num2);
}
===
package Interface;
public class Calculator implements Calc {
@Override
public int add(int num1, int num2) {
// TODO Auto-generated method stub
return num1 + num2;
}
@Override
public int substract(int num1, int num2) {
// TODO Auto-generated method stub
return num1 - num2;
}
}
==========
package Interface;
public abstract class CompleteCalc extends Calculator{
@Override
public int times(int num1, int num2) {
// TODO Auto-generated method stub
return num1 * num2;
}
@Override
public int divide(int num1, int num2) {
if(num2!=0) {
return num1/num2;
}
return Calc.ERROR;
}
public void showInfo() {
System.out.println("Clac 인터페이스를 구현하였습니다.");
}
}
============
package Interface;
public class CalculatorTest {
public static void main(String[] args) {
int num1 = 10;
int num2 = 5;
CompleteCalc calc = new CompleteCalc();
System.out.println(calc.add(num1, num2));
System.out.println(calc.substract(num1, num2));
System.out.println(calc.times(num1, num2));
System.out.println(calc.divide(num1, num2));
calc.showInfo();
}
}
ㄴ위의 코드를 살펴보면 CompleteClac 클래스만이 인스턴스를 생성할 수 있다. -> Calculator 클래스는 추상클래스이기에 인스턴스를 생성할 수 없다.
Calc <- Calculator <- CompleteCalc 형태로 상위 클래스를 이룬다.
그렇다면 하위클래스의 형 변환은 어떻게 이루어 지는지 살펴보자
-> 상속관계에서 하위클래스는 상위 클래스 자료형으로 묵시적 형 변환이 가능하다. 인터페이스도 같다.
CompleteCalc 클래스는 상위 클래스인 Calculator 형이면서 Calc 형이기도 하다.
Calc calc = new CompleteCalc();
Calc newCalc = calc; -> Clac 형 변수인 newCalc에 calc변수를 대입한다.
newCalc가 사용할 수 있는 메서드를 살펴보자. showInfo 메서드를 사용할 수 없다.
Calc형으로 선언한 변수에서 사용할 수 있는 메서드는 Calc 인터페이스에 선언한 메서드뿐이다.
정리!!
=> 인터페이스를 구현한 클래스가 있을 때 그 클래스는 해당 인터페이스형으로 묵시적 형 변환이 이루어지며, 형 변환되었을 때 사용할 수 있는 메서드는 인터페이스에서 선언한 메서드 뿐이다.
- 인터페이스와 다형성
인터페이스를 사용하는 이유는 무엇일까?
=> 인터페이스는 말 그대로 껍데기일 뿐이다. 하지만 인터페이스는 메서드를 통해서 앞으로 전개될 코드를 추측할 수 있도록 해주는 역할을 한다.
인터페이스의 다형성
: 인터페이스를 사용하면 다형성을 구현하여 확장성 있는 프로그램을 만들 수 있다.
클라이언트 프로그램을 많이 수정하지 않고 기능을 추가하거나 다른 기능을 사용할 수 있다.
package InterfaceEX;
public interface Scheduler {
public void getNextCall();
public void sendCallToAgent();
}
==
package InterfaceEX;
public class RoundRobin implements Scheduler {
@Override
public void getNextCall() {
System.out.println("상담 전화를 순서대로 대기열에서 가져옵니다.");
}
@Override
public void sendCallToAgent() {
System.out.println("다음 순서 상담원에게 배분합니다.");
}
}
=====
package InterfaceEX;
public class PriorityAllocation implements Scheduler{
@Override
public void getNextCall() {
System.out.println("고객 등급이 높은 고객의 전화를 먼저 가져옵니다.");
}
@Override
public void sendCallToAgent() {
System.out.println("업무 skill 값이 높은 상담원에게 우선적으로 배분합니다.");
}
}
=====
package InterfaceEX;
public class LeastJob implements Scheduler{
@Override
public void getNextCall() {
System.out.println("상담 전화를 순서대로 대기열에서 가져옵니다.");
}
@Override
public void sendCallToAgent() {
System.out.println("현재 상담 업무가 업거나 대기가 가장 적은 상담원에게 할당합니다.");
}
}
=====
package InterfaceEX;
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();
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();
}
}
ㄴ 위의 코드를 살펴보자
: 인터페이스를 생성하고 세 개의 클래스는 해당 인터페이스를 implements 한다.
test클래스를 살펴보면 입력값에 따라 클래스로 생성한 인스턴스는 scheduler 형 변수에 대입할 수 있게된다.
그리고 어떤 인스턴스가 생성이 된거와 상관없이 인터페이스에서 제공하는 메서드를 사용하면 된다.
이것이 인터페이스를 활용해 다형성을 구현한 것이다.
- 인터페이스 요소 살펴보기
인터페이스에서는 메서드를 구현하지 않는다고 하였다. 하지만 java 8 부터는 인터페이스에서 메서드를 구현하여 활용할 수 있도록 하였다. 그 방법이 2가지가 있는데 알아보자.
## 디폴트 메서드
: 기본으로 제공되는 메서드이다. 인터페이스에서 구현하여 인터페이스를 구현한 클래스에서는 디폴트 메서드를 사용할 수 있다. 디폴트 메서드를 선언할 때는 default 예약어를 사용하면 된다.
-> 디폴트 메서드 재정의
: 구현되어 있는 디폴트 메서드가 새로 생성한 클래스에서 원하는 기능이 아니라면 하위클래스에서 재정의 할 수 있다.
## 정적 메서드
: static 예약어를 사용하여 선언하며 클래스 생성과 무관하게 사용할 수 있다.
**특징! 정적 메서드를 사용할 때는 참조변수 없이 인터페이스 이름으로 직접참조가 가능하다!!
- 인터페이스 활용하기
## 한 클래스가 여러 인터페이스 구현
package InterfaceEX1;
public interface Buy {
void buy();
default void order() {
System.out.println("구매 주문");
}
}
====
package InterfaceEX1;
public interface Sell {
void sell();
default void order() {
System.out.println("판매 주문");
}
}
===
package InterfaceEX1;
public class Customer implements Buy, Sell{
@Override
public void sell() {
System.out.println("판매");
}
@Override
public void buy() {
System.out.println("구매");
}
@Override
public void order() {
System.out.println("customer 클래스에서 구현된 메서드 등장");
}
}
======
package InterfaceEX1;
public class CustomerTest {
public static void main(String[] args) {
Customer customer = new Customer();
Buy buyer = customer; //중요!! Customer 클래스형인 customer를 Buy 인터페이스형인 buyer에 대입하여 형 변환
buyer.buy();
buyer.order(); //
Sell seller = customer;
seller.sell();
seller.order(); //
if(seller instanceof Customer) {
Customer customer2 = (Customer)seller;
customer2.buy();
customer2.sell();
customer2.order(); //디폴트 메소드는 인터페이스를 implements 한 클래스에서 재정의한 메소드 등장( vmc 자바가상머신이 메소드를 참조하는 방법 )
}
}
}
ㄴ위의 코드를 살펴보자
Customer 클래스는 Buy, Sell 인터페이스를 implements 하고 있다.
인터페이스는 구현 코드나 멤버변수를 갖고 있지 않기에 여러개를 동시에 구현할 수 있다.
두 인스턴스에 같은 order 디폴트 메서드가 생성되어 있지만, 두 인터페이스를 implements 한 Customer 클래스에서 재정의된 order 메서드가 사용된다.
## 인터페이스 구현과 클래스 상속 함께 쓰기
package InterfaceEX3;
public interface Queue {
void enQueue(String title);
String deQueue();
int getSize();
}
======
package InterfaceEX3;
import java.util.ArrayList;
public class Shelf {
protected ArrayList<String> shelf;
public Shelf() {
shelf = new ArrayList<String>();
}
public ArrayList<String> getShelf(){
return shelf;
}
public int getCount() {
return shelf.size();
}
}
=======
package InterfaceEX3;
public class BookShelf extends Shelf implements Queue {
@Override
public void enQueue(String title) {
shelf.add(title);
}
@Override
public String deQueue() {
// TODO Auto-generated method stub
return shelf.remove(0);
}
@Override
public int getSize() {
// TODO Auto-generated method stub
return getCount();
}
}
========
package InterfaceEX3;
public class BookShelfTest {
public static void main(String[] args) {
Queue shelfQueue = new BookShelf();
shelfQueue.enQueue("일");
shelfQueue.enQueue("이");
shelfQueue.enQueue("삼");
System.out.println(shelfQueue.deQueue());
System.out.println(shelfQueue.deQueue());
System.out.println(shelfQueue.deQueue());
}
}
인터페이스 Queue와 Shelf 클래스를 생성 -> BookShelf 클래스는 각각을 상속하고 implements 한다.
출처 : DO IT! 자바프로그래밍 (저 : 박은종)
'개인공부 > JAVA' 카테고리의 다른 글
JAVA - Inner Class, Lambda , Stream (0) | 2021.03.21 |
---|---|
JAVA - CLASS (0) | 2021.03.16 |
JAVA - Abstract (0) | 2021.03.10 |
JAVA - Class 와 Object - 2 (0) | 2021.03.08 |
JAVA - Class와 Object (1) (0) | 2021.03.02 |