티스토리 뷰

 

이 콘텐츠는 아래와 같은 내용을 담고 있습니다.

  • 인터페이스란
  • 인터페이스 선언과 구성
  • 인터페이스 특징
  • 인터페이스 접근 지정자
  • 예제

 


 

 

인터페이스가 뭔데 그래서?

 일상생활에서도 인터페이스란 말은 많이 들어봤을 것이다. 그런데 정확히 인터페이스가 뭐지? 하고 물으면, 막상 입 밖으로 잘 떨어지지 않는다. 자바에서 인터페이스는 쉽게 말하자면, '어떠한 객체가 특정 인터페이스를 사용할 때, 그 인터페이스 메서드를 구현하도록 강제하는 것'이라고 정의할 수 있다. (이 정의는 생활코딩 이 고잉님의 인터페이스 강의에서 발췌해온 정의다.) 이렇게 딱딱하게만 말하면 머릿속에 박히질 않으니, 현실세계에 빗대어 인터페이스를 설명해보려 한다.

 

 어느 날 공장 사장님이 개발자 둘을 불러놓고, 플러그를 만들라고 지시했다. 개발자들은 둘 다 플러그를 만들어 가져왔지만, 죄다 사장님한테 털렸다. 왜? 둘다 다른걸 만들었기 때문이다. 

 

커뮤니케이션의 중요성

 A 개발자는 110v용 플러그를 만들고, B 개발자는 220v용 플러그를 만들었다. 하지만 아쉽게도 둘다 사장님이 원하는 공업용 플러그가 아니었고, 그들이 밤새서 만든 플러그는 쓸모가 없어졌다. 지금 그들은 아마 플로그 모양을 죄다 3핀으로 바꾸느냐고 또 야근을 하고 있을지도 모른다. 왜 이런 일이 발생했을까? 

바로 커뮤니케이션 미스가 났기 때문이다. 사장이 공업용 3핀짜리를 만들어 달라고 정확하게 얘기했으면, 꽂는 부분은 같은 모양으로 통일할 수 있었다. 

 

인터페이스를 쓰는 이유는 간단하다.  위와 같은 소통의 부재를 해결하기 위해, 공통적인 속성에 대해 서로 맞춰가는 약속하는 것이다. 

 

 

다시 우리의 언어, 자바로 돌아와서 다시 이야기를 하자. 현실 세계나 여기나 같은 목적으로 인터페이스는 만들어졌다. 서로 공통 속성에 대한 틀을 만들어 약속한 것이다. 어떻게 만들든, 구체적인 것은 구현자 본인이 책임을 지게 하고, 그 형식은 맞춰달라고 하는 것이다. 청사진, 설계도라고 보면 된다. 

좀 더 정확히 이해하기 위해 인터페이스의 구성을 보자.

 

 

 

선언

 인터페이스는 아래와 같이 선언한다.

//인터페이스 작성 문법
//[ACCESS MODIFIER] interface INTERFACENAME [extents ANOTHER_INTERFACE]
public interface Interface_Sample {


}

 인터페이스는 implement를 통해 상속받으며, 클래스 상속과 다르게 다중 상속이 가능하다.

public class GetSampleInterface implements Interface_Sample,RemoteControl {

	@override methods....
}

 

 

구성

 인터페이스 내부의 구성은 추상 클래스와 비슷하다. 멤버 변수와 메서드가 포함될 수 있으며, 메서드는 추상 메서드로 구현부가 없다. 이는 인터페이스가 틀(Form)만을 설계하기 때문에 추상 메서드를 지니며, 구현의 책임은 전가한다고 보면 된다.

//인터페이스 작성 문법
//[ACCESS MODIFIER] interface INTERFACENAME [extents ANOTHER_INTERFACE]
public interface Interface_Sample {
    //멤버 변수
    int a = 12;

    //메소드
    void print();


}

 

 

인터페이스의 특징

인터페이스는 아래의 특징을 가진다.

 

  1. 인터페이스 멤버 변수는 컴파일 시 상 수화된다.
  2. 특정 접근 지정자(static, private, default)를 제외하고는 구현부가 없다.
  3. 인터페이스 메서드는 접근 지정자를 붙이지 않아도, 기본적으로 public abstract 키워드로 설정된다.

 

1. 인터페이스의 멤버 변수는 컴파일 시 상수화 된다.

 컴파일 시 정말로 상 수화되는지 확인하기 위해, 명시적으로 붙인 변수와 붙이지 않은 변수를 생성하고, 값을 변경해 보았다.

public interface Interface_Sample {
    static final int interface_static_final_num = 3;
    
	//컴파일시 public static final 로 변경됨
    int interface_num = 3;
}

 

컴파일 에러

 컴파일부터 상수라 규정할 수 없다며 에러를 뱉는다. 인터페이스 멤버 변수는 컴파일 시 public static final 키워드가 붙게 된다. 인터페이스를 설계의 관점으로 본다면, 쉽게 이해할 수 있다. 설계도에 속성을 명시했다는 것은 그 속성은 바뀌면 안 되기 때문에 명시를 한 것이다. 이와 같은 논리로 인터페이스가 갖는 변수도 상수가 된다.

 

 

2. 메서드(접근 지정자 private, default, static 제외)의 구현부가 없다.

 위에 구성에서 언급했듯, 인터페이스는 추상화된 형식만을 가지고 있기 때문에 구현부가 없다. 추상 메서드와 동일하다. 따라서, 인터페이스를 상속받는 모든 클래스는 메서드를 반드시 구현해야 사용할 수 있다. 

 

반드시 추상메서드는 구현해야한다.

구현을 하지 않으면, 컴파일조차 되지 않는다. 이런 의미에서 인터페이스가 본인의 메서드를 강제한다 라고 하는 것이다.

 

 

3. 인터페이스 메서드의 기본 접근 지정자는 public abstract이다. 

 

 메서드 앞에 접근 지정자를 붙이지 않는다면, 기본적으로 public abstract 형식을 갖는다. 때문에 해당 인터페이스를 상속받았다면, 반드시 구현하여 사용하여야 한다. 또한 public 접근 지정자이기 때문에 외부에서 메서드를 사용할 수 있다.

public interface Interface_Sample {

    //멤버 변수
    int a = 12;

    //메소드
    void print();
    
}

 

public class GetSampleInterface implements Interface_Sample {

    public static void main(String[] args) {
        GetSampleInterface test = new GetSampleInterface();
        test.print();
    }

    @Override
    public void print() {
        System.out.println("Hello Interface");
    }
}

 

 그렇다면 private은 어떨까? private 접근 지정자는 상속에서도 보았듯 자기 자신 외에는 닫혀있다. 인터페이스에도 마찬가지다. 아무리 인터페이스를 상속받아도 private은 인터페이스 본인 이외 건들 수 없다. 그럼 여기서 의문이 생길 것이다.

 

"아까 추상 메서드만 들어간다며? 구현 안 했는데, 상속받아서도 구현이 안되면 쓸모없는 것 아냐? "

 

정확하다. 구현이 안된다는 가정 하엔 쓸모가 없다. 2번에서 언급했던  private , default, static 이 세 접근 지정자에 대해 알아보자.  

 

 

프라이빗, 스태틱, 디폴트 

 

Private Method

 Public 접근 지정자가 외부에서 사용할 수 있도록 메서드를 열어 놓았던 것이라면, Private은 외부에서 사용하지 못하는, 즉, 인터페이스 내부적으로 사용하기 위한 접근 지정자다. 당연히 상속 밭은 클래스에서 접근, 재정의가 불가능하다. 인터페이스 내부적 구현을 목적으로 한 키워드이기 때문에 private 키워드는 인터페이스 내에서 반드시 구현을 해야 한다. 주로 정적 메서드(Static Method)나 디폴트 메서드(Default Method)에서 사용된다.

 

아래의 두 키워드는 JDK 8 이상에서 추가된 메서드이다.

 

Static Method

 인스턴스 없이 인터페이스 타입으로 호출하는 메서드다. static 키워드는 인스턴스와 생성 타이밍이 다르다.(이 부분은 추후에 포스팅 예정이다. 우선은 static이 먼저 생성된다는 것만 알아두자.) 당연히 재정의 할 수 없으며, 정적 메서드(Static Method) 역시 반드시 구현부가 존재해야 한다.

 

Default Method

 기본적으로 구현부를 가지고 있는 메서드이다. 디폴트 메서드는 다른 추상 메서드와 달리 구현을 강제하지 않는다. 인터페이스에서 이미 구현부를 가지고 있기 때문이다. 사용자의 선택에 따라 디폴트로 제공된 메서드를 써도 되고, 오버 라이딩해도 된다.

 

 

 

 

 

인터페이스의 활용 예제

 TV 리모컨 인터페이스가 있다고 해보자. 인터페이스는 다음과 같다.

public interface RemoteControl {

    static final int TRUNON = 999;
    static final int TRUNOF = 998;
    String thing = "리모컨";

    void turn_on();
    void trun_off();

    private int getTrunon(){
        return TRUNON;
    }
    private int getTrunof(){
        return TRUNOF;
    }
    default void printDiscription(){
        System.out.println(thing+"입니다.");
        System.out.println("turn on 과 off 의 기능이 있습니다.");
        System.out.println("turn on : " + getTrunon());
        System.out.println("turn off : " + getTrunof());

    }

}

 

 이 인페이스를 받는 LGTV 와 SamsungTV 가 있다고 하자. 두 TV 클래스는 다음과 같다.


public class LGTV implements RemoteControl{

    public void watchNetflix(){
        System.out.println("넷플릭스가 나온다.");
    }

    @Override
    public void turn_on() {
        System.out.println("LG 티비가 켜졌다");
    }

    @Override
    public void trun_off() {
        System.out.println("LG 티비가 꺼졌다.");
    }

    @Override
    public void printDiscription() {
        RemoteControl.super.printDiscription();
        System.out.println("넷플릭스 기능이 있습니다.");
    }
}
public class SamsungAITV implements RemoteControl{
    @Override
    public void turn_on() {
        System.out.println("삐빕 TV ON");
    }
    
    @Override
    public void trun_off() {
        System.out.println("삐빕 TV OFF");
    }

    public void recommendChannel(){
        System.out.println("오늘의 추천채널입니다.");
    }

    @Override
    public void printDiscription() {
        System.out.println("삼성 TV 설명서입니다.");
        RemoteControl.super.printDiscription();
        System.out.println("채널 추천 기능이 있습니다.");
    }
}

 

 인터페이스를 이용하면 다음과 같은 방식으로 두 TV를 모두 조작할 수 있다.

public class User {

    public static void main(String[] args) {
        RemoteControl myRemote;

        myRemote = new SamsungAITV();
        myRemote.printDiscription();
        myRemote.turn_on();
        myRemote.trun_off();

        System.out.println("TV 변경");

        myRemote = new SamsungAITV();
        myRemote.printDiscription();
        myRemote.turn_on();
        myRemote.trun_off();


    }
}

 

 

 어디서 많이 본 적 있지 않은가? 상속에서 본 업 캐스팅과 매우 유사하지 않은가? 물론 LG와 Samsung의 고유 메서드는 쓸 수 가없다. 하지만 인터페이스로 정의해놓은 부분들을 이용하는 데에는 지장이 없다. 이것이 인터페이스의 장점이다.

instaceof를 잘 사용하면, 인터페이스 인스턴스를 받아서 다운 캐스팅해서 쓰는 것도 충분히 가능하다.

 

 


포스팅에 문제가 있거나, 설명이 잘못된 부분 지적 환영합니다.

더 나은 퀄리티의 콘텐츠를 제공할 수 있도록 노력하겠습니다.

읽어주셔서 감사합니다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
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
글 보관함