본문 바로가기
개발자 꿈나무의 하루/01_Boot Camp

(네이버클라우드 부트캠프) 29일차 - Java프로그래밍 기초(인터페이스)

by kk_naks 2024. 7. 5.

1. 인터페이스

  1.1 인터페이스의 필요성

     - 메인 메서드가 각 클래스를 호출 할때, 호출메서드명이 상이하다.

BlueWorker w1 = new BlueWorker();
WhiteWorker w2 = new WhiteWorker();
JubuWorker w3 = new JubuWorker();

// 각 노동자에게 일을 시키는 방법이 다르다.
// 왜? 
// => 메서드 호출 방법이 다르기 때문에
w1.doFight();
w2.doZingZing();
w3.doSsingSsing();

  1.2 인터페이스의 적용

     - 동일한 호출명으로 메서드를 호출 할 수 있다.

public interface Worker {

  // 호출 규칙?
  // => 메서드 형식을 의미한다.
  // => 메서드의 몸체는 정의하지 않는다.
  // => 메서드의 몸체는 이 규칙에 따라 만드는 클래스에서 정의하는 것이다.
  //
  // 문법
  // => public abstract 리턴타입 메서드명(파라미터,...);
  // => public과 abstract는 모두 생략 가능.
  // => public 외에 다른 접근 범위는 사용할 수 없다.
  //    (규칙은 공개되어야 하니까!)
  //
  void execute();
  //=> public abstract void execute();
}

class WhiteWorker implements Worker {
  @Override
  public void execute() {
    System.out.println("사무직 노동자가 일을 합니다.");
  }
}
Worker w1 = new BlueWorker();
Worker w2 = new WhiteWorker();
Worker w3 = new JubuWorker();

w1.execute();
w2.execute();
w3.execute();

  1.3 인터페이스의 관계

     - 호출자 : 클라이언트로 구현체를 호출 하는 클래스

     - 피호출자 : 구현체로 인터페이스의 규칙을 적용받아 메소드를 생성

 

2. 인터페이스 구성요소 

  2.1 인터페이스 기본요소

     - 인터페이스 기본형은 public abstract 이다.

interface MyInterface {
  // 규칙1) 인터페이스에 선언되는 모든 메서드는 public 이다.
  //   - 인터페이스에 정의하는 메서드는 호출 규칙이다.
  //   - 규칙은 공개되어야 한다.
  // 규칙2) 인터페이스에 선언되는 모든 메서드는 추상 메서드로 선언한다.
  //   - 인터페이스에 선언하는 메서드는 호출 규칙을 정의한 것이다.
  //   - 규칙은 클래스가 따라야 한다.
  //   - 그래서 인터페이스에 선언되는 모든 메서드는 몸체를 구현하지 않는다.
  public abstract void m1();

  // public 을 생략할 수 있다.
  abstract void m2(); // public 이 생략된 것이다. (default) 아니다!

  // abstract 를 생략할 수 있다.
  public void m3();

  // public, abstract 모두 생략할 수 있다.
  void m4();

  // => private, protected, (default)는 없다.
  //  private void m5(); // 컴파일 오류!
  //  protected void m6(); // 컴파일 오류!
  void m7(); // 이건 (default) 아니라, public 이 생략된 것이다.

}

 

     - 구현부의 형식은 다음과 같다.

// 2) 인터페이스 구현
abstract class MyInterfaceImpl implements MyInterface {
  @Override
  public void m1() {}

  // public 보다 접근 범위를 좁힐 수는 없다.
  @Override
  //  private void m2() {}  // 컴파일 오류!
  //  protected void m2() {} // 컴파일 오류!
  //  void m2() {} // 컴파일 오류!
  public void m2() {} // OK!

  // 인터페이스의 모든 메서드를 구현해야 한다.
  // 한 개라도 빠뜨린다면 concrete 클래스가 될 수 없다.
  // 추상 클래스로 선언해야 한다.
}

 

     - 메인클래스에서 인터페이스의 사용은 다음과 같다.

public class Exam01 {

  public static void main(String[] args) {
    // 인터페이스 레퍼런스 선언
    MyInterface obj = null;

    // 인터페이스의 구현체 생성
    // - 인터페이스를 구현한 클래스의 객체라면
    //   언제든 해당 인터페이스의 레퍼런스에 담을 수 있다.
    obj = new MyInterfaceImpl2();

    // 인터페이스는 규칙이기 때문에
    // 구체적인 구현 내용이 없다.
    // 그래서 인스턴스를 생성할 수 없다.
    //
    //    obj = new MyInterface(); // 컴파일 오류!
  }

}

  2.2 디폴트메서드

     - 디폴트 메서드는 인터페이스에서 미리 구현하는 메서드이다. 

- 인터페이스 받는 클래스에서 구현메서드를 재정의 하지 않아도 된다. 
- 하지만, 클래스에서 구현을 강제할 수 없다. 

// 인터페이스 - private 메서드
package com.eomcs.oop.ex09.b;

interface MyInterface4 {

  void m1();

  default void m2() {
    System.out.println("MyInterface4.m2()");
    x();
  };

  default void m3() {
    System.out.println("MyInterface4.m3()");
    x();
  };
}

// 2) 인터페이스 구현
class MyInterface4Impl implements MyInterface4 {
  @Override
  public void m1() {
    // 인터페이스에 선언된 오버라이딩 전의 default 메서드를 호출하고 싶다면,
    //    super.m2(); // 수퍼 클래스(Object)에서 m2()를 찾아 올라간다. Object에는 m2()가 없기 때문에 컴파일 오류!
    //    MyInterface4.m2(); // m2()는 인스턴스(non-static) 메서드이기 때문에 인터페이스 이름으로 직접 호출 불가!
    MyInterface4.super.m2();

    System.out.println("MyInterface4Impl.m1()");
  }

  @Override
  public void m2() {
    System.out.println("MyInterface4Impl.m2()");
  }
}

public class Exam04 {

  public static void main(String[] args) {
    MyInterface4 obj = new MyInterface4Impl();

    obj.m1();
    System.out.println("-----------------------------");

    obj.m2();
    System.out.println("-----------------------------");

    obj.m3();
    System.out.println("-----------------------------");
  }

}

  2.3 기타 메서드

     - 인터페이스 필드

- 인터페이스의 필드는 public static final이다.
- 인스턴스를 생성 할 수 없기 때문에 무조건 상수만 사용 가능이다. 

 

     - private 메서드

- 인터페이스 내부에서 사용할 매서드고 private로 정의한다. 
interface MyInterface4 {

  void m1();

  default void m2() {
    System.out.println("MyInterface4.m2()");
    x();
  };

  default void m3() {
    System.out.println("MyInterface4.m3()");
    x();
  };

  // 인터페이스 내부에서 사용할 메서드라면
  // private 접근 범위를 갖는
  // 구현 메서드를 정의할 수 있다.
  // 언제?
  // - 해당 기능을 m2()와 m3() 처럼 여러 메서드에서 사용해야 할 경우
  //   그 공통 코드를 다음과 같이 private 구현 메서드로 정의하면 될 것이다.
  //
  private void x() {
    System.out.println("MyInterface4.x()");
  }
}

 

3. 인터페이스의 활용

  3.1 인터페이스의 상속

상속, 인터페이스 관계 case 1. case 2. case 3.
My obj = new My();
obj.m1();
obj.m2();
obj.X();
B obj = new My();
obj.m1();
obj.m2();
obj.X();
A obj = new My();
obj.m1();
obj.m2();
obj.X();

 

  3.2 인터페이스의 다중상속

     - 여러개의 인터페이스를 상속 받아 인터페이스를 만들수 있다.

- 상속받는 인터페이스에서 리턴타입이 같은 메소드명을 상속 받을 수 있다.
- 리턴타입이 같은 메소드명을 받을 수 있는 이유는 상속받는 메소드가 추상메서드 이기 때문에 가능하다.
- 반대로 리턴 타입이 다르면 컴파일러는 두 메소드를 구분 할 수 없어 상속이 불가능하다. 

  3.3 인터페이스의 다중구현

     - 같은 원리로 구현부 역시 여러개의 인터페이스를 받을 수 있다.