여행을 개발하다
인터페이스(Interface) 본문
안녕하세요!!
오늘의 포스팅 주제는 '인터페이스(Interface)'입니다.
지난 포스팅에서 Java는 다중 상속이 금지되어 있으며,
그 이유를 C++에서 다중 상속 시 발생 우려가 있는 Diamond of Death 현상으로 설명하였습니다.
인터페이스(Interface)는
이러한 Java의 한계점을 보완하기 위해 마련된 기능이라고 보시면 됩니다.
즉, 다른 클래스를 상속 받은 서브 클래스들의 공통점을 추출해서 사용이 가능하도록 돕습니다.
그럼 지금부터 인터페이스의 특징에 대해 알아보겠습니다.
1. 인터페이스(Interface)의 정의
- 무조건 정적(static) 멤버 변수(상수)와 추상 메소드로만 구성되는 클래스의 특별한 형태.
C++에서도 '어떤 클래스로부터 상속을 받을지'에 대한 모호성으로 다중 상속이 금지되어 왔습니다.
하지만, 다중 상속이 아니더라도 적어도 '다중 상속 효과'를 내기 위한 작업이 필요하기도 했는데요.
이에 대한 보완점으로 나온 것이 '추상 클래스, 메소드(Abstract Class, Method)'였습니다.
즉, 실재하는 것이 아닌 가상의 메소드를 사용하여 상속 효과를 내는 것이지요.
Java에서 이와 동일한 기능을 하는 것이 Interface라고 보시면 됩니다.
2. 인터페이스 선언 규칙
- 인터페이스 선언 시, 'interface + 인터페이스 명'으로 선언한다.
- 인터페이스에서 변수 선언 시, Java Complier가 public static final을 자동으로 붙여준다.
- 인터페이스는 메소드 선언 시, Java Complier가 public abstract을 컴파일러가 자동으로 붙여준다.
인터페이스를 선언하는 방법은 클래스와 크게 다르지 않습니다.
클래스를 선언할 때, 'class + 클래스 명'으로 선언했었죠?
인터페이스는 class 대신에 'interface + 인터페이스 명'으로 선언하시면 됩니다.
인터페이스는 다중 상속 효과를 내기 위한 것이기 때문에,
인터페이스의 멤버 변수와 메소드는 클래스의 그것들과도 역시 조금 다릅니다.
인터페이스의 멤버 변수 선언시에는 public static final를, 메소드는 public abstract을 Java Compiler가 자동으로 붙여주기 때문입니다.
아래 그림에서 PI, LIMIT 이라는 멤버 변수와 move()와, erase()라는 메소드의 접근 권한 지정은
제가 직접 적어준 것입니다. 즉, 생략이 가능합니다.
Draw라는 인터페이스의 멤버 변수와 메소드는 다음과 같이 선언해도 똑같은 효과를 냅니다.
여기서 잠시 final의 의미에 대해 알아보겠습니다.
* final을 멤버 변수 선언시 앞에 붙여주면 그 변수는 프로그램에서 값을 변경할 수 없다.
다시 말해, 상수가 됩니다.
* final을 메소드 선언시 앞에 붙여주면 그 메소드는 override 할 수 없다.
* final을 클래스 선언시 앞에 붙여주면 그 클래스는 상속시킬 수 없다.
값을 변경해서 사용할 수 없다는 것이 공통점이고,
이는 더 이상의 상속을 금지한다는 의미로 볼 수도 있겠죠?
이처럼 다중 상속 효과를 낼 수 있는 인터페이스는 참 편리한 기능을 한다고 생각합니다.
그러나 그만큼 제약 조건 역시 존재합니다.
그럼 제약 조건이 무엇인지 인터페이스의 특징을 통해 살펴보도록 하겠습니다.
3. 인터페이스의 특성
- 클래스는 인터페이스를 상속 받을 수 없고, 반대로 인터페이스는 클래스를 상속 받을 수 없다.
클래스에서 인터페이스를 상속 받는 효과를 내려면, extends 대신 implements라는 예약어를 사용한다.
- 클래스는 클래스로부터 상속 받을 수 있듯이, 인터페이스는 인터페이스로부터 상속이 가능하다.
- 클래스는 다중 상속을 허용하지 않지만 인터페이스는 다중 상속을 허용한다.
- 아무런 내용을 가지지 않는 인터페이스를 표시(marker) 인터페이스라고 부른다.
자식 클래스가 부모 클래스의 있는 멤버 변수와 메소드를 물려받는 것을 '상속'이라고 표현합니다.
그래서 '상속 받았다'라고 표현을 했는데요.
하지만 인터페이스는 상속이라는 말 대신, '구현(implement)'이라는 말을 사용합니다.
그래서 예약어도 'extends' 대신에 'implements'를 사용합니다.
예를 들어, 'Line'이라는 클래스를 선언함과 동시 'Point'라는 클래스를 상속 받고, 'Draw', 'Graphic'이라는 인터페이스를 구현할 때는 다음과 같이 표현할 수 있습니다.
다중 상속 역시 문제 없이 가능합니다.
하지만 신기하게 Graphics라는 인터페이스는 아무런 멤버 변수와 메소드가 없네요...
이를 표시 인터페이스(Marker Interface)라고 부릅니다.
표시 인터페이스는 일반적인 인터페스와 동일하지만, 아무런 멤버 변수와 메소드도 선언되지 않은 인터페이스를 의미합니다.
표시 인터페이스의 기능은 '직렬화'와 '타입 체크'라고 알려져 있는데요.
표시 인터페이스를 구현 받아 사용하는 클래스를 객체화 할 때,
어떻게 형태를 바꾸어 사용해야 하는지에 대한 일종의 '주석(Annotation)'의 역할을 합니다.
하지만 세부적인 기능은 무엇이고,
어떤 부분에서 사용할 수 있을지 저도 공부를 좀 더 해야 할 것 같습니다.
지금까지 인터페이스에 대한 기본 이론에 대해 알아보았습니다.
세부적인 구현 방법과 사용 예들은 저의 학습이 완료되는 즉시 포스팅하겠습니다.
'BackEnd > Java' 카테고리의 다른 글
[Java] Wrapper Class(래퍼 클래스) (0) | 2021.08.04 |
---|---|
ArrayList (0) | 2019.05.15 |
Diamond of Death 현상 (다중 상속의 문제점) (0) | 2019.05.14 |
클래스의 상속(Inheritance) (0) | 2019.05.14 |
StringTokenizer, hasMoreTokens(), nextToken() (0) | 2019.05.14 |