포스트

Day29 Java프로그래밍 기초(Interface)

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 {

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    // 호출 규칙?
    // => 메서드 형식을 의미한다.
    // => 메서드의 몸체는 정의하지 않는다.
    // => 메서드의 몸체는 이 규칙에 따라 만드는 클래스에서 정의하는 것이다.
    //
    // 문법
    // => 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();

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    // 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() {}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    // public 보다 접근 범위를 좁힐 수는 없다.
    @Override
    //  private void m2() {}  // 컴파일 오류!
    //  protected void m2() {} // 컴파일 오류!
    //  void m2() {} // 컴파일 오류!
    public void m2() {} // OK!
    
    // 인터페이스의 모든 메서드를 구현해야 한다.
    // 한 개라도 빠뜨린다면 concrete 클래스가 될 수 없다.
    // 추상 클래스로 선언해야 한다.   }
    
  • 메인클래스에서 인터페이스의 사용은 다음과 같다.

    public class Exam01 {

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    public static void main(String[] args) {
      // 인터페이스 레퍼런스 선언
      MyInterface obj = null;
    
      // 인터페이스의 구현체 생성
      // - 인터페이스를 구현한 클래스의 객체라면
      //   언제든 해당 인터페이스의 레퍼런스에 담을 수 있다.
      obj = new MyInterfaceImpl2();
    
      // 인터페이스는 규칙이기 때문에
      // 구체적인 구현 내용이 없다.
      // 그래서 인스턴스를 생성할 수 없다.
      //
      //    obj = new MyInterface(); // 컴파일 오류!
    }
    

    }

2.2 디폴트메서드

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



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// 인터페이스 - 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 {

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    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 인터페이스의 다중구현

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



이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.