Java

인터페이스

인터페이스란?

인터페이스(interface)는 다소 추상적인 개념이다. 인터페이스가 무엇인가를 철학적으로 논하려면 책 한권이 필요할지도 모르겠다. 하지만 우리는 철학 공부를 하는 것이 아니라 공학 공부를 하는 것이니 자바의 기능으로서 인터페이스를 받아들이면 되겠다.

필자가 앞선 수업에서 인터페이스를 abstract, final와 함께 대표적인 규제라고 언급했던 것 기억하는가? 인터페이스의 역할은 이렇다. 어떤 객체가 있고 그 객체가 특정한 인터페이스를 사용한다면 그 객체는 반드시 인터페이스의  메소드들을 구현해야 한다. 만약 인터페이스에서 강제하고 있는 메소드를 구현하지 않으면 이 에플리케이션은 컴파일 조차 되지 않는다.

예제

우선 단순한 예를 보자.

package org.opentutorials.javatutorials.interfaces.example1;

interface I{
    public void z();
}

class A implements I{
	public void z(){}
}

클래스 A 뒤의 implements I는 이 클래스가 인터페이스 I를 구현하고 있다는 의미다. 그것은 3행의 interface I의 맴버인 public void z() 메소드를 클래스 A가 반드시 포함하고 있어야 한다는 뜻이다. 따라서 위의 코드는 문제가 없다. 인터페이스의 의미를 좀 더 분명하게 하기 위해서 8행의 public void z(){}를 삭제하자. 컴파일 에러가 발생할 것이다. 

인터페이스와 상속은 다르다. 상속이 상위 클래스의 기능을 하위 클래스가 물려 받는 것이라고 한다면, 인터페이스는 하위 클래스에 특정한 메소드가 반드시 존재하도록 강제한다. 이러한 규제가 왜 필요한지는 뒤에서 알아본다.

또 사용하는 키워드도 다르다. 클래스를 선언 할 때는 class를 사용하지만 인터페이스는 interface를 사용한다.

또 상속은 extends를 사용하지만 인터페이스는 implements를 사용한다. 이를 바탕으로 위의 예제를 해설해보면 아래와 같다.

클래스 A는 인터페이스 I를 '구현' 한다.

실질적인 쓰임

계산기 예제에 인터페이스를 도입해보자. 계산기 기능이 필요한 프로젝트를 진행하는데 시간이 촉박하다. 그래서 계산기 클래스는 개발자 A가 만들고, 개발자 B는 그 클래스를 사용하는 로직을 만들다고 해보자. 이런 경우 개발자 B는 개발자 A가 계산기를 잘 만들어서 나중에 제출할 것이라고 기대하고 개발을 진행할 것이다. 그리고 아래와 같이 가짜 로직을 만들어서 코드를 작성했다.

package org.opentutorials.javatutorials.interfaces.example1;
class CalculatorDummy{
    public void setOprands(int first, int second, int third){}
    public int sum(){
        return 60;
    }
    public int avg(){
        return 20;
    }
}
public class CalculatorConsumer {
    public static void main(String[] args){
		CalculatorDummy c = new CalculatorDummy();
		c.setOprands(10,20,30);
		System.out.println(c.sum()+c.avg());
	}
}

개발자 A가 Calculator를 만드는데 3개월이 필요하다고 한다면 그 시간을 단축하기 위해서 위와 같은 코드를 작성하는 이유가 공감 할 수 있을 것이다. 3개월이 지나고 개발자 A가 Calculator 클래스를 완성해서 인계해줬다. 아래는 그 코드다.

package org.opentutorials.javatutorials.interfaces.example1;

class Calculator {
    int left, right;
	public void setOprands(int left, int right) {
		this.left = left;
		this.right = right;
	}
	public void sum() {
		System.out.println(this.left + this.right);
	}
	public void avg() {
		System.out.println((this.left + this.right) / 2);
	}
}

아뿔싸. 개발자 A는 setOprands의 매개변스를 2개 받고 있지만 개발자 B는 이 메소드가 변수 3개를 받을 것이라고 생각한 것이다. 이건 마치 해저터널의 공사가 중간에서 만나지 않은 것과 같은 상황이다. 이때부터 신경전이 시작된다. 경우에 따라서는 치열하게 다투게 되고 프로젝트는 파국으로 치닫는다. 이러한 문제를 해결하기 위한 가장 좋은 방법은 무엇일까? 협업자 상호간에 구체적인 약속을 하면 된다. 특히 그 약속을 코드 안에서 할 수 있다면 참 좋을 것이다. 그렇다. 인터페이스가 필요한 순간이다. 

클래스 Calculator를 사용할 개발자가 이 클래스가 가지고 있어야 할 메소드를 인터페이스로 만들어서 제공하는 것이다. 반대의 경우도 가능하다. 만드는 쪽에서 인터페이스를 제공하면 된다. 양쪽의 개발자는 이 인터페이스를 구현한 클래스 Calculator와 CalculatorDummy를 각각 구현하면 된다.

이렇게 해서 만들어진 코드를 보자. 아래는 약속을 정의하고 있는 인터페이스이다.

package org.opentutorials.javatutorials.interfaces.example2;

public interface Calculatable {
    public void setOprands(int first, int second, int third) ;
	public int sum(); 
	public int avg();
}

다음은 인터페이스를 구현한 가짜 클래스를 임시로 사용해서 만든 에플리케이션이다.

package org.opentutorials.javatutorials.interfaces.example2;
class CalculatorDummy implements Calculatable{
    public void setOprands(int first, int second, int third){
    }
    public int sum(){
        return 60;
    }
    public int avg(){
        return 20;
    }
}
public class CalculatorConsumer {
    public static void main(String[] args) {
		CalculatorDummy c = new CalculatorDummy();
		c.setOprands(10, 20, 30);
		System.out.println(c.sum()+c.avg());
	}
}

다음 코드는 인터페이스에 따라서 구현된 클래스이다.

package org.opentutorials.javatutorials.interfaces.example2;

class Calculator implements Calculatable {
    int first, second, third;
	public void setOprands(int first, int second, int third) {
		this.first = first;
		this.second = second;
		this.third = third;
	}
	public int sum() {
		return this.first + this.second + this.third;
	}
	public int avg() {
		return (this.first + this.second + this.third) / 3;
	}
}

이제 해야 할 일은 가짜 클래스인 CalculatorDummy를 실제 로직으로 교체하면 된다.

package org.opentutorials.javatutorials.interfaces.example2;
public class CalculatorConsumer {
    public static void main(String[] args) {
		Calculator c = new Calculator();
		c.setOprands(10, 20, 30);
		System.out.println(c.sum()+c.avg());
	}
}

이렇게해서 인터페이스를 이용한 협업에 대해서 알아봤다. 인터페이스를 이용해서 서로가 동일한 메소드를 만들도록 규약을 만들어서 공유한 결과 각자가 상대의 일정이나 구현하는 방식에 덜 영향을 받으면서 에플리케이션을 구축 할 수 있었다.

인터페이스의 규칙

인터페이스의 몇가지 규칙을 더 알아보자.

하나의 클래스가 여러개의 인터페이스를 구현 할 수 있다. 

클래스 A는 메소드 x나 z 중 하나라도 구현하지 않으면 오류가 발생한다.

package org.opentutorials.javatutorials.interfaces.example3;

interface I1{
    public void x();
}

interface I2{
	public void z();
}

class A implements I1, I2{
	public void x(){}
	public void z(){}	
}

인터페이스도 상속이 된다.

package org.opentutorials.javatutorials.interfaces.example3;

interface I3{
    public void x();
}

interface I4 extends I3{
	public void z();
}

class B implements I4{
	public void x(){}
	public void z(){}	
}

인터페이스의 맴버는 반드시 public이다.

아래 코드는 오류를 발생한다. 인터페이스는 그 인터페이스를 구현한 클래스를 어떻게 조작할 것인가를 규정한다. 그렇기 때문에 외부에서 제어 할 수 있는 가장 개방적인 접근 제어자인 public만을 허용한다. public을 생략하면 접근 제어자 default가 되는 것이 아니라 public이 된다. 왜냐하면 인터페이스의 맴버는 무조건 public이기 때문이다.

package org.opentutorials.javatutorials.interfaces.example3;

interface I5{
    private void x();
}

abstract vs interface

인터페이스와 추상 클래스는 서로 비슷한 듯 다른 기능이다. 인터페이스는 클래스가 아닌 인터페이스라는 고유한 형태를 가지고 있는 반면 추상 클래스는 일반적인 클래스다. 또 인터페이스는 구체적인 로직이나 상태를 가지고 있을 수 없고, 추상 클래스는 구체적인 로직이나 상태를 가지고 있을 수 있다.

댓글

댓글 본문
  1. nextLevel
  2. jsum01
    240415
  3. wwwqiqi
    완료
  4. Alan Turing
    09/13
  5. PassionOfStudy
    복습 4일차!
  6. 김은희
    20220615 완료

    하나의 클래스가 여러개의 인터페이스를 구현할 수 있다
    인터페이스도 상속이 된다
    인터페이스의 맴버는 반드시 public이다

    abstract vs interface 약간 헷갈림 다시 보고 정리 ...
  7. PassionOfStudy
    interface!
  8. dogchang
    220508 interface 학습완료.

    2회차 복습 필요.
  9. 자바잡아
    22.05.03 Final Attack Ride. I. I. I. Interface!
  10. 20220429
  11. 모찌말랑카우
    22.02.17
  12. 민둥빈둥
    22.02.13
  13. aesop0207
    220209 Wed.
  14. 행달
    22.02.06 완료!
  15. Mark Kim
    특정 메소드의 구현을 강제하도록 하는 인터페이스의 기능이 여러 클래스를 작성할 시 협업에 도움이 된다는 사실을 처음 알게되었습니다. 실제로 대부분의 어플리케이션은 다수의 팀들에 의해서 만들어지고, 유지보수가 되기 때문에 특정 기능 구현에 대한 통일된 이해가 매우 중요하게 여겨지는데, 인터페이스가 특정 메소드의 구현 방식을 강제하여 이 역할을 수행하게 되는군요..
  16. 드림보이
    2021.12.17. 인터페이스 파트 수강완료
  17. syh712
    2021-12-09
    <인터페이스>
    1. 인터페이스의 역할: 어떤 객체가 있고 그 객체가 특정한 인터페이스를 사용한다면 그 객체는 반드시 인터페이스의 메소드들을 구현.
    인터페이스는 하위 클래스에 특정한 메소드가 반드시 존재하도록 강제한다.
    상속은 extends를 사용하지만 인터페이스는 implements를 사용

    2. 협업자 상호간에 구체적인 약속을 하면 된다. 특히 그 약속을 코드 안에서 할 수 있다면 참 좋을 것이다. 그렇다. 인터페이스가 필요한 순간임.
    public interface Calculatable {
    public void setOprands(int first, int second, int third) ;
    public int sum();
    public int avg();
    => 인터페이스를 이용해서 서로가 동일한 메소드를 만들도록 규약을 만들어서 공유한 결과 각자가 상대의 일정이나 구현하는 방식에 덜 영향을 받으면서 에플리케이션을 구축

    3. 인터페이스의 규칙
    - 하나의 클래스가 여러개의 인터페이스를 구현 할 수 있다.
    - 인터페이스도 상속이 된다.
    - 인터페이스의 맴버는 반드시 public이다.
    - abstract vs interface:
    ==인터페이스는 클래스가 아닌 인터페이스라는 고유한 형태를 가지고 있는 반면 추상 클래스는 일반적인 클래스다.
    ==인터페이스는 구체적인 로직이나 상태를 가지고 있을 수 없고, 추상 클래스는 구체적인 로직이나 상태를 가지고 있을 수 있다.
  18. 네제가해냈습니다
    211119
  19. H4PPY
    1104
  20. 베이스박
    2021.9.16 학습완료
  21. super1Nova
    210831
  22. 이땅콩
    interface는 "규칙"이라고 말할 수 있을 것 같습니다.
    규칙은 간결하고 핵심만 말해야 가독성에 좋죠.
    그래서 인터페이스는 다른 로직 / 상태를 가지고 있을 수 없군요!
  23. Eunyoung Eunice Kang
    2021.8.16(월) 완료
  24. 악어수장
    2021-5-13
  25. 악어수장
    2021-05-10 완료
  26. 김태현
    요점
    A,B가 공통으로 사용할 인터페이스
    따로 작업한 뒤 모아서 객체 수정 뒤 실행한다
  27. 김태현
    인터페이스 내의 접근제어자는 누구나 접근할 수 있는 public 이여야 한다
    인터페이스에는 사용할 기능만 선언할 뿐 자세한 구현이 없다
    ( ) 구현 중괄호가 아예 없다.
    인터페이스가 메뉴라면 implements는 구체적인 기능이다

    다음 코드
    implements에서 어떤 기능으로 사용할 것인지 정하여 구현한다.
  28. 김태현
    1/3 동영상 요점

    package org.opentutorials.javatutorials.interfaces.example1;

    interface I{
    public void z();
    }

    // 구현을 강제
    // 구현할 수 있는 대괄호 [ ]가 아예 없다.

    class A implements I{
    // i를 class A에 의무적으로 구현해야 한다.

    public void z(){}
    // i에 있는 public void z()을 복사(오버라이딩)해서
    [ ] 내에 사용할 코드를 구혀하라는 의미
    }

    //
  29. 김태현
    public 뒤에 오는 메서드
    기존 interface는 abstract 추상메소드만 가질수 있었는데 자바 8에서는 디폴드, 스테틱으로도 구현가능

    public static void ~

    또는
    default int exce (int i, int j)
  30. 김태현
    3회 수업완료
    인터페이스는 구체적인 로직이나 상태를 가지고 있을 수 없고,
    추상 클래스는 구체적인 로직이나 상태를 가지고 있을 수 있다.
  31. EunSeok Kang
    잘수강합니다. 20200814
  32. hvii
    202008012
  33. 푸른쿠우
    2020-06-06 수강완료
    감사합니다.
  34. 김승민
    2020-04-22
    감사합니다~
  35. 진리의지은
    2020-01-20 수강완료.
  36. ㅇㄻㄴㅁㄴㅇㄹ
    박재민 하트 김민주
  37. 134214
    박재민 ㅗ
  38. dhkdn
  39. 테러맨
    예전에 배웠던 내용들이지만 잘 이해가 안갔었는데
    이해가 조금 되는것 같아요 ㅎ 감사합니다
  40. 허공
    감사합니다!
  41. PassionOfStudy
    191008(화) - (2)
    수강완료~
  42. 홍주호
    20190915 완료
  43. silver94
    수강 잘들엇습니다!
  44. 다나가
    190905 - 수강완료~~
  45. doevery
    수강완료
  46. 아롱범
    abstract / interface의 차이는 그 사용목적을 생각해보면 될 것 같아요. 문법은 그 이후 부차적인 것이고....

    abstract - 개발 환경의 특수성을 고려하여 클래스의 구현을 개발자에게 위임
    interface - 혼선을 피하기 위한 개발자들간 상호 약속
  47. 7월 15일 시작
    클래스class 상속의 키워드는 extends를 사용한다. 다중 상속이 불가능하다.
    인터페이스interface 구현은 implements를 사용한다. 다중 구현이 가능하다.
  48. 6/17시작
    어렵네요 ㅎㅎㅎㅎ...

    7월 8일 완료
  49. following
    항상 감사합니다.!
  50. ouove
    이렇게 쉽게 잘 가르쳐주시다니...정말 감사합니다