인터페이스

박정훈·2021년 1월 23일
0

java

목록 보기
13/15

인터페이스

클래스 혹은 프로그램이 제공하는 기능을 명시적으로 선언하는 역할을 한다. 인터페이스는 추상 메서드와 상수로만 이루어져 있다. 구현된 코드가 없기 때문에 인스턴스를 생성할 수도 없다.

인터페이스는 클라이언트 프로그램에 어떤 메서드를 제공하는지 미리 알려주는 명세(specification) 또는 약속의 역할을 한다.

인터페이스의 역할은 인터페이스를 구현한 클래스가 어떤 기능의 메서드를 제공하는지 명시하는 것이다. 그리고 클라이언트 프로그램은 인터페이스에서 약속한 명세대로 구현한 클래스를 생성해서 사용하면 된다.

public interface Calc {
	double PI = 3.14;
    	int ERROR = -9999999999;
        
        int add(int num1, int num2);
        int substract(int num1, int num2);
        int times(int num1, int num2);
        int divide(int num1, int num2);
}

인터페이스에서 선언한 메서드는 모두 구현 코드가 없는 추상 메서드이다. 이들 메서드는 public abstract 예약어를 명시적으로 쓰지 않아도 컴파일 과정에서 자동으로 추가되어 추상 메서드로 변환된다.
그리고 인터페이스에서 선언한 변수는 모두 컴파일 과정에서 값이 변하지 않는 상수로 자동 변환된다.
public static final 예약어를 쓰지 않아도 자동으로 추가되어 상수로 인식한다.

인터페이스를 클래스가 사용하는 것을 '클래스에서 인터페이스를 구현한다(implements)'라고 표현한다.
인터페이스에 선언한 기능을 클래스가 구현한다는 의미로 implements 예약어를 사용한다.
Calc 인터페이스를 Calculator 클래스에서 구현하는 방법은 다음과 같다.

public class Calculator implements Calc {
	@Override
    	public int add(int num1, int num2) {
        	return (num1 + num2);
        }
        @Override
        public int substract(int num1, int num2) {
        	return (num1 - num2);
        }
}

그런데 위와 같이만 코드를 작성하면 오류가 발생한다. 왜냐하면 Calc 인터페이스에 포함된 추상 메서드를 구현하지 않았기 때문이다.
따라서 추상 메서드를 구현하거나 Calculator 클래스를 추상 클래스로 만들면 해결된다.

인터페이스도 상속과 같이 하위 클래스는 상위 클래스 자료형으로 묵시적 형 변환할 수 있다.

public class CompleteCalc extends Calculator {
	@Override
    	public int times(int num1, int num2) {
        	return (num1 * num2);
        }
        
        @Override
        public int divide(int num1, int num2) {
        	if (num2 != 0)
            		return (num1 / num2);
            	else
                	return (Calc.ERROR);
        }
}

CompleteCalc 클래스는 상위 클래스인 Calculator 형이면서, Calc 인터페이스를 구현하였으므로 Calc형이기도 하다.
따라서 다음과 같은 코드가 가능하다.

Calc calc = new CompleteCalc();

인터페이스를 구현한 클래스가 있을 때 그 클래스는 해당 인터페이스형으로 묵시적 형 변환이 이루어지며, 형 변환되었을 때 사용할 수 있는 메서드는 인터페이스에서 선언한 메서드 뿐이다.

  • 디퐅르 메서드와 정적 메서드 구현부가 없다면 인터페이스는 껍데기다.

인터페이스를 사용하면 다형성을 구현하여 확장성 있는 프로그램을 만들 수 있다. 즉 클라이언트 프로그램을 많이 수정하지 않고 기능을 추가하거나 다른 기능을 사용할 수 있다.

인터페이스 상수

인터페이스는 추상 메서드로 이루어지므로 인스턴스를 생성할 수 없으며 멥버 변수도 사용할 수 없다. 그런데 인터페이스에 아래 코드와 같이 변수를 선언해도 오류가 발생하지 않는다. 그 이유는 인터페이스에 선언한 변수를 컴파일하면 public static final이 붙어서 상수로 변환되기 때문이다.

public interface Calc {
	double PI = 3.14;
    	int ERROR = -9999999999;
}

Calc 인터페이스에 선언한 변수 PI를 컴파일하면
double PI = 3.14; 코드가
public static final double PI = 3.14로 변환된다.

어떤 인터페이스를 구현한 여러 클래스에서 사용할 메서드가 클래스마다 같은 기능을 제공하는 경우가 있다.
자바 8부터는 인터페이스 활용성을 높이기 위해 디폴트 메서드와 정적 메서드 기능을 제공한다. 디폴트 메서드는 인터페이스에서 구현 코드까지 작성한 메서드이다. 인터페이스를 구현한 클래스에 기본적으로 제공할 메서드인 것이다.
정적 메서드는 인스턴스 생성과 상관없이 사용할 수 있는 메서드이다. 디폴트 메서드나 정적 메서드가 추가 됐더라도 인터페이스는 여전히 인스턴스를 생성할 수 없다.

디폴트 메서드

말 그대로 기본으로 제공되는 메서드이다. 디폴트 메서드는 인터페이스에서 구현하지만, 이후 인터페이스를 구현한 클래스가 생서되면, 그 클래스에서 사용할 기본 기능이다. 디폴트 메서드를 선언할 때는 default 예약어를 사용한다.
디폴트 메서드는 일반 메서드와 똑같이 구현하면 되고, 메서드 자료형 앞에 default 예약어만 써 주면 된다.
하위 클래스에서 디폴트 메서드를 재정의 할 수 있다.

정적 메서드

정적 메서드는 staic 예약어를 사용하여 선언하며 인스턴스 생성과 무관하게 사용할 수 있다. 정적 메서드를 사용할 때는 인터페이스 이름으로 직접 참조하여 사용한다.

private 메서드

자바 9부터는 인터페이스에 private 메서드를 구현할 수 있다. private 메서드는 인터페이스를 구현한 클래스에서 사용하거나 재정의할 수 없다. 따라서 기존에 구현된 코드를 변경하지 않고 인터페이스를 구현한 클래스에서 공통으로 사용하는 경우에 private 메서드로 구현하면 코드 재사용성을 높일 수 있다. 또한 클라이언트 프로그램에 제공할 기본 기능을 private 메서드로 구현하기도 한다.
private 메서드는 코드를 모두 구현해야 하므로 추상 메서드에 private 예약어를 사용할 수는 없지만, static 예약어는 함께 사용할 수 있다. private static 메서드는 정적 메서드에서 호출하여 사용한다.

public interface Calc {
	default void description() {
    		System.out.println("정수 계산기를 구현합니다.");
        	myMethod();
        }
        
        static int total(int[] arr) {
        	int total = 0;
            
            	for (int i: arr) {
                	total += i;
                }
                myStaticMethod();
                return total;
        }
        
        private void myMethod() {
        	System.out.println("private 메서드입니다.");
        }
        
        private static void myStaticMethod() {
        	System.out.println("private static 메서드입니다.");
        }
}

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

인터페이스는 한 클래스가 여러 인터페이스를 구현할 수 있다.

public interface Buy {
	void buy();
}

public interface Sell {
	void sell();
}

public class Customer implements Buy, Sell {
	@Override
    	public void sell() {
        	System.out.println("구매하기");
        }
        
    	@Override
        public void buy() {
        	System.out.println("판매하기");
        }
}

두 인터페이스에 이름이 같은 메서드가 선언되었다고 해도 구현은 클래스에서 이루어지므로, 어떤 메서드를 호출해야 하는지 모하하지 않다. 이렇게 두 인터페이스를 구현한 Customer 클래스는 Buy형이자 Sell 형이기도 하다.

public class CustomerTest {
	public static void main(String[] args) {
    		Customer customer = new Customer();
    		Buy buyer = customer;
            	buyer.buy();
                Sell seller = customer;
                seller.sell();
                
                if (seller instanceof Customer) {
                	Customer customer2 = (Customer)seller;
                    	customer2.buy();
                        customer2.sell();
                }
    	}
}

두 인터페이스의 디폴트 메서드가 중복되는 경우는 두 인터페이스를 구현하는 클래스에서 재정의해야 한다.

인터페이스 상속

인터페이스 간에 상속이 가능하다. 인터페이스 간 상속은 구현 코드를 통해 기능을 상속하는 것이 아니므로 형 상속(type inheritance)라고 부른다. 클래스의 경우에는 하나의 클래스만 상속받을 수 있지만, 인터페이스는 여러 개를 동싱세 상속받을 수 있다. 한 인터페이스가 여러 인터페이스를 상속받으면, 상속 받은 인터페이스는 상위 인터페이스에 선언한 추상 메서드를 모두 가지게 된다.
클래스를 상속할 때 사용한 extends 예약어를 그대로 사용한다.

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

한 클래스에서 클래스 상속과 인터페이스 구현을 모두 할 수 있다.

public class BookShelf extends Shelf implements Queue {
	...
}

인터페이스를 이용한 다형성의 구현

인터페이스는 클래스가 제공할 기능을 선언하고 설계하는 것이다. 만약 여러 클래스가 같은 메서드를 서로 다르게 구현하는 경우에 우선 인터페이스에 메서드를 선언한 다음 인터페이스를 구현한 각 클래스에 같은 메서드에 대해 다양한 기능을 구현하면 된다. 이것이 인터페이스를 이용한 다형성의 구현이다.
인터페이스를 잘 정의하는 것이 확장성 있는 프로그램을 만드는 시작이다.

예를 들어 회사마다 사용하는 데이터베이스가 다르다.
데이터베이스의 기능을 수행할 인터페이스 정의
인터페이스 정의에 맞게 여러 데이터베이스 관련 모듈을 개발

JDBC(Java DataBase Connectivity)

자바와 데이터베이스를 연결해 주는 역할을 한다. 자바와 데이터베이스를 연결하려면 여러 기능을 수행해야 하는데 그 중 하나가 Connection을 생성하고 연결하는 것이다.
자바와 데이터베이스를 연결하기 위해 사용하는 Connection은 인터페이스이다. 이 인터페이스에는 여러 메서드들이 미리 구현되어 있으며, 이들 메서드를 사용하여 데이터베이스를 접근하는 자바 프로그램을 구현하면 된다.
JDBC는 자바에서 데이터베이스를 어떻게 사용할 것인지를 기술한 명세, 즉 약속이다.

정리

  • 클래스가 인터페이스를 구현하기 위해 사용하는 예약어는 implements이다.
  • 클래스가 인터페이스를 구현할 때 인터페이스에 선언한 메서드를 모두 구현하지 않으면 그 클래스는 추상클래스가 된다.
  • 인터페이스에 선언한 변수는 컴파일할 때 상수로 변환된다.
  • 한 인터페이스를 여러 클래스가 다양한 방식으로 구현한 경우에 프로그램에서 인터페이스에 선언된 메서드를 사용할 때 각 클래스의 구현 내용과 상관 없이 동일한 방식으로 사용할 수 있다. 이렇게 같은 코드가 여러 구현 내용으로 실행되는 객체 지향 특성을 다형성이라고 한다.
  • 인터페이스에서 구현 코드를 제공하는 메서드는 디폴트 메서드와 정적 메서드이다.
  • 한 클래스에서 여러 인터페이스를 구현할 수 있다.

출처

do it 자바프로그래밍 입문

profile
정팔입니다.

0개의 댓글