본문 바로가기

프로그래밍 언어/JAVA

JAVA 입문 - 인터페이스 활용

지난 글: [프로그래밍 언어/JAVA] - JAVA 입문 - 인터페이스 요소

 

한 클래스가 여러 인터페이스를 구현하는 경우

한 클래스가 여러 클래스를 상속받으면 메서드 호출이 모호해지는 문제가 발생할 수 있다. 하지만 인터페이스는 한 클래스가 여러 인터페이스를 구현할 수 있다. 예로 Buy 인터페이스와 Sell 인터페이스를 구현한 Customer 클래스를 만들어보자.

추상 메서드 buy( )와 sell( )이 각각 선언된 인터페이스 Buy와 Sell을 Customer 클래스에 구현했다. 인터페이스는 구현 코드나 멤버 변수를 가지지 않기에 여러 개를 동시에 구현할 수 있다. 두 인터페이스에 이름이 같은 메서드가 선언되었다 해도 구현은 클래스에서 이루어지므로 어떤 메서드를 호출해야 하는지 모호하지 않은 것이다.

 

이렇게 두 인터페이스를 구현한 Customer 클래스는 Buy형이자 Sell형이기도 하여 아래와 같이 테스트 프로그램을 만들 수 있다.

Buy buyer = c1; 처럼 c1을 Buy 인터페이스형 변수에 대입하여 형 변환을 일으키고 Buy 인터페이스에 선언한 메서드만 호출할 수 있다.

 

두 인터페이스의 디폴트 메서드가 중복되는 경우

정적 메서드는 인스턴스 생성과 상관없이 사용할 수 있다. Customer 클래스가 Buy, Sell 인터페이스를 구현하고 Buy 인터페이스와 Sell 인터페이스에 똑같은 정적 메서드 pay( )를 선언했다면, Buy.pay( )와 Sell.pay( )로 특정하여 호출할 수 있기에 문제가 되지 않는다. 헌데 디폴트 메서드는 인스턴스를 생성해야 호출할 수 있는 메서드이기에 아래처럼 이름이 같은 디폴트 메서드가 두 인터페이스에 있으면 문제가 된다.

위 오류 메시지는 디폴트 메서드가 중복되었으니 두 인터페이스를 구현하는 Customer 클래스에서 재정의하라는 뜻이다.

Customer 클래스에서 디폴트 메서드를 재정의하면 Customer 클래스를 생성하여 사용할 때 재정의된 메서드가 호출된다. 즉 아래처럼 호출하면 Customer에서 재정의된 order( ) 메서드가 호출된다.

출력 결과

여기서 주의점은 c1이 Buy형으로 변환되고 buyer.order.( )를 호출하면 Buy에 구현한 디폴트 메서드가 아닌 Customer 클래스에 재정의한 메서드가 호출된다. 이는  JAVA 입문 - 메서드 오버라이딩

편에서 설명한 이유과 같은 것으로, 인스턴스의 클래스형이 Customer여서 Customer형의 재정의된 메서드가 호출된 것이다.

 

인터페이스 상속하기

인터페이스 간에도 상속이 가능하다. 인터페이스 간 상속은 구현 코드를 통해 기능을 상속하는 것이 아니므로 형 상속(type inheritance)이라고 부른다. 클래스의 경우 하나의 클래스만 상속 받을 수 있지만 인터페이스는 여러 개를 동시에 상속받을 수 있다. 한 인터페이스가 여러 인터페이스를 상속받으면 상속받은 인터페이스는 상위 인터페이스에 선언한 추상 메서드를 모두 가지게 된다. 아래와 같은 경우를 생각해보자.

MyInterface 인터페이스는 X, Y 인터페이스를 상속받고, MyClass 클래스는 MyInterface를실제 사용할 수 있도록 구현한다. MyInterface는 두 인터페이스를 상속받고 자신이 추상 메서드를 1개 갖고 있으므로 상속받은 후 추상 메서드를 총 3개 갖게 된다. 따라서 MyClass가 구현해야 할 추상 메서드는 3개이다.

 

인터페이스 구현과 클래스 상속 함께 쓰기

한 클래스에서 클래스 상속과 인터페이스 구현을 모두 할 수도 있다. 아래처럼 Queue 인터페이스를 구현하고 Shelf 클래스를 상속받는 BookShelf 클래스를 구현해보자.

 

Shelf 클래스

 

Queue 인터페이스

4행의 enQueue( ) 메서드는 입력되는 요소 값을 배열의 맨 뒤에 추가한다. 6행의 deQueue( ) 메서드는 배열에서 맨 앞에 있는 요소를 제거하고 그 값을 반환한다.

 

BookShelf 클래스

 

BookShelfTest 클래스

출력 결과

앞으로 자바 프로그램을 개발하면서 이미 제공되고 있는 클래스나 인터페이스를 사용한 프로그램을 자주 접하게 될거라고 한다. 특히 실무에서 프레임워크나 기존 소스 코드를 사용해 개발하는 경우가 많다고 하다.

 

실무에서 인터페이스를 사용하는 경우

인터페이스는 클래스가 제공할 기능을 선언하고 설계하는 것이다. 만약 여러 클래스가 같은 메서드를 서로 다르게 구현한다면 어찌 해야 할까? 먼저 인터페이스에 메서드를 선언한 다음 인터페이스를 구현한 각 클래스에서 같은 메서드에 대해 다양한 기능을 구현하면 된다. 

 

이런 경우를 생각해보자. 어느 회사에서 시스템을 개발했다. 이 시스템은 자료를 저장하기 위해 데이터베이스를 사용한다. 처음에는 MySQL 데이터베이스를 사용했는데, 이 시스템을 다른 회사에 가서 설치하려니 오라클 데이터베이스를 사용하여 설치해 달라한다. 또 다른 회사는 MS-SQL을 사용한다고 한다. 프로그램은 하나인데 사용하는 데이터베이스가 제각각인 것이다. 이 프로그램의 웹 페이지나 모바일 페이지는 데이터베이스와 관계없이 수행된다.데이터 베이스와 연관되는 코드는 프로그램의 특정 부분인 것이다. 이런 경우 데이터베이스 기능을 수행할 인터페이스를 정의하고 그에 맞게 여러 데이터베이스 관련 모듈을 개발하면 된다. 다음은 사용자 정보를 처리하는 모듈 그림이다.

사용자 정보를 데이터베이스에 입력하거나 업데이터하거나 삭제하는 기능을 UserInfoDao 인터페이스에서 정의한다. 그리고 여러 데이터베이스에 맞게 구현하는 것은 각 클래스가 담당한다. 웹 페이지나 그 밖의 다른 클래스에서 이 기능이 필요하면 UserInfoDao 인터페이스를 구현하여 사용할 수 있다. 인터페이스를 잘 정의하는 것이 확장성 있는 프로그램을 만드는 시작이라고 한다.

 

참고 서적: 자바 프로그래밍 입문 - 박은종

'프로그래밍 언어 > JAVA' 카테고리의 다른 글

JAVA 입문 - String 클래스  (0) 2022.05.31
JAVA 입문- Object 클래스  (0) 2022.05.30
JAVA 입문 - 인터페이스 요소  (0) 2022.05.28
JAVA 입문 - 인터페이스와 다형성  (0) 2022.05.27
JAVA 입문 - 인터페이스  (0) 2022.05.26