class
가 아니고 interface
키워드를 사용한다.public
또는 default
접근 제어자만 사용 가능.public static final
이다. (생략 가능하다.)public abstract
이며, 생략가능Calc calc = new CompleteCacl();
interface IFoo{
public static final int MEMBER_VAR = 10; //변하지 않는 상수는 대문자_ 형식으로 사용하기 때문에 여기도 사용한다.
int MEMBER_VAR2 = 20 ; //이렇게 사용해도됨 public static final;
public abstract void methodA(int param);
void methodB(int param); //public abstract
}
class Foo implements IFoo{
@Override
public void methodA(int param) {
System.out.println(param);
}
@Override
public void methodB(int param) {
System.out.println(param);
}
}
인터페이스 간에도 상속이 가능하데, 이 경우 extends
키워드를 사용한다. (구현하는 것이 아니라서 extends 사용)
implements
키워드를 사용한다.클래스간의 상속과 달리 인터페이스간의 상속은 다중 상속 가능하다.
interface Walkable{
void walk();
}
interface Runable{
void run();
}
interface Jumpable extends Walkable, Runable{
void jump();
// 워크, 런이 다 포함되어 있음
}
class Jumper implements Jumpable{
// 3개다 구현해야함 -?
@Override
public void walk() {
System.out.println("걷다");
}
@Override
public void run() {
System.out.println("달리다");
}
@Override
public void jump() {
System.out.println("뛰다");
}
}
public interface Scheduler {
public void getNextCall();
public void sendCallToAgent();
}
public class RoundRobin implements Scheduler{
@Override
public void getNextCall() {
System.out.println("상담 전화를 순서대로 대기열에서 가져옵니다.");
}
@Override
public void sendCallToAgent() {
System.out.println("다음 순서의 상담원에게 배분합니다.");
}
}
public class PriorityAllocation implements Scheduler{
@Override
public void getNextCall() {
System.out.println("고객등급이 높은 고객의 call을 먼저 가져옵니다.");
}
@Override
public void sendCallToAgent() {
System.out.println("업무 숙련도가 높은 상담원에게 먼저 배분합니다.");
}
}
public class LeastJob implements Scheduler{
@Override
public void getNextCall() {
System.out.println("상담 전화를 순서대로 대기열에서 가져옵니다.");
}
@Override
public void sendCallToAgent() {
System.out.println("현재 상담업무가 없거나 상담대기가 가장 적은 상담원에게 할당합니다.");
}
}
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; // 왜 리턴을 넣지?
/**
* return을 사용하는 이유
* return은 값을 반환하거나 메소드를 호출한 곳으로 되돌아갈 때 사용하는 예약어이다
* 만약 메소드 내부에서 return값이 void일때 return을 하면 여기서 메소드를 끝내겠다는 의미
* return을 호출하면 나머지 로직을 실행하지 않고 함수를 종료하는 의미이다.
*/
}
scheduler.getNextCall();
scheduler.sendCallToAgent();
}
}
인터페이스에도 default 메소드를 구현할 수 있다. 접근제어자는 항상 public
키워드를 사용해야 한다.
인터페이스 철학과 맞지 않으나, 기존에 사용하던 인터페이스가 개선되어,
모든 자식 메소드에 동일하게 구현되어야 하는 메소드가 생긴 경우에 쉽게 기능을 추가하기 위해 만들어졌다.
많은 클래스들이 인터페이스를 상속하는 경우 선택적으로 오버라이드해서 사용할 수 있다.
interface IFoo2{
void abstractMethod();
default void defaultMethod(){ //디폴트 메소드
System.out.println("default method");
}
}
class FooTwo implements IFoo2{
@Override
public void abstractMethod() {
System.out.println("abstract method implemented");
}
// @Override // overriding not necessary 반드시 오버라이딩 해야 하는 것은 아님.
// public void defaultMethod() {
// System.out.println("overriden default method");
// }
}
//처음부터 디폴트메소드를 구현하고 시작하는 것은 철학적으로 맞지않음 원래 abstract 메소드만 있음
class SuperFoo{ //인터페이스가 있는데 부족한 부분이 있어서 메소드를 생성해서 사용하고 있었다
public void defaultMethod(){
System.out.println("default method in super class");
}
}
class Foo3 extends SuperFoo implements IFoo2 {
@Override
public void abstractMethod() {
System.out.println("abstract metho implemented");
}
}
인터페이스의 static 메소드 : 클래스 메소드와 동일하게 사용 가능하다.
interface IFoo {
static void staticMethod() {
System.out.println("static method");
}
}
public class Main {
public static void main(String[] args) {
IFoo.staticMethod(); // static method
}
}