손영배 블로그 누구나 쉽게 이해하고 습득하기

인터페이스(interface)란? 본문

Interview

인터페이스(interface)란?

손영배 2019. 8. 31. 00:49

인터페이스의 역할

자바에서 인터페이스(interface)는 객체의 사용 방법을 정의한 타입니다. 인터페이스는 객체의 교환성을 높여주기 때문에 다형성을 구현하는데 매우 중요한 역할을 한다. 

 

인터페이스(interface)는 개발 코드와 객체가 서로 통신하는 접점 역할을 한다. 개발 코드가 인터페이스의 메소드를 호출하면 인터페이스는 객체의 메소드를 호출시킨다. 그렇기 때문에 개발 코드는 객체의 내부 구조를 알 필요가 없고 인터페이스의 메소드만을 알고 있으면 된다.

 

개발 코드가 직접 객체의 메소드를 호출하면 간단한데 왜 중간에 인터페이스를 두는지 의문점이 생긴다.? 그 이유는 개발 코드를 수정하지 않고, 사용하는 객체를 변경할 수 있도록 하기 위해서이다. 인터페이스는 하나의 객체가 아니라 여러 객체들과 사용이 가능하므로 어떤 객체를 사용하느냐에 따라서 실행 내용과 리턴값이 다를 수 있다. 따라서 개발 코드 측면에서는 코드 변경 없이 실행 내용과 리턴값을 다양화할 수 있다는 장점을 가지게 된다. 

 

클래스는 필드, 생성자, 메소드를 가지는데 비해 인터페이스는 상수와 메소드만(디폴트, 정적)을 구성 멤버로 가진다. 인터페이스는 객체로 생성할 수 없기 때문에 생성자를 가질 수 없다. 

interface 인터페이스명 {
	//상수
    타입 상수명 = 값;
    
    //추상메소드
    타입 메소드명(매개변수, ...);
    
    //디폴트 메소드
    default 타입 메소드명(매개변수, ...) {...}
    
    //정적 메소드
    static 타입 메소드명(매개변수, ...) {...}
}

상수 필드(Constant Field)

상수는 인터페이스에 고정된 값으로 런타임 시에 데이터를 바꿀 수 없다. 상수를 선언할 때에는 반드시 초기값을 대입해야 한다.

public interface RemoteControl {
	public int MAX_VOLUME = 10;
   	public int MIN_VOLUME = 0;
}

추상 메소드 선언

인터페이스를 통해 호출된 메소드는 최종적으로 객체에서 실행된다. 그렇기 때문에 인터페이스의 메소드는 실행 블록이 필요없는 추상 메소드로 선언한다. 추상 메소드는 리턴타입, 메소드명, 매개변수만 기술되고 중괄호 {}를 붙이지 않는 메소드를 말한다. 인터페이스에 선언된 추상 메소드는 모두 public abstact의 특성을 갖기 때문에 public abstact를 생략하더라도 자동적으로 컴파일 과정에서 붙게 된다.

public interface RemoteControl {
	
    //추상 메소드 메소드 선언부만 작성
    public void turnOn();
    public void turnOff();
    public void setVolume(int volume);
}

디폴트 메소드 선언

[public] default 리턴타입 메소드명(매개변수, ...) { ... }

interface RemoteControl {

	//디폴트 메소드 .....-> 실행 내용까지 작성
    default void setMute(boolean mute){
		if(mute){
    		System.out.println("무음 처리합니다.");
    	} else {
        	System.out.println("무음 해제합니다.");
    	}
    }
}
   

 정적 메소드 선언

형태는 클래스의 정적 메소드와 완전 동일하다. 

public interface RemoteControl {
	//정적 메소드
	static void changeBattery(){
    	System.out.println("건전지를 교환합니다.");
    }
}

구현 클래스

구현 클래스는 보통의 클래스와 동일한데, 인터페이스 타입으로 사용할 수 있음을 알려주기 위해 클래스 선언부에 implements 키워드를 추가하고 인터페이스명을 명시해야 한다. 

public class 구현클래스명 implements 인터페이스명 {
	//인터페이스에 선언된 추상 메소드의 실체 메소드 선언
}
public class Television implements RemoteControl {
	//필드
    private int volume;
    
    //turnOn() 추상 메소드의 실체 메소드
    public void turnOn(){
    	System.out.println("TV를 켭니다.");
    }

	//turnOff() 추상 메소드의 실체 메소드
    public void turnOff(){
    	System.out.println("TV를 끕니다.");
    }
    
    //setVolume() 추상 메소드와 실체 메소드
    public void setVolume(int volume) {
    	if(volume > RemoteControl.MAX_VOLUME){
        	this.volume = RemoteControl.MAX_VOLUME;
        } else if(volume < RemoteControl.MIN_VOLUME){
        	this.volume = RemoteControl.MIN_VOLUME;
        } else {
        	this.volume = volume;
        }
    	System.out.println("현재 TV 볼륨 : " + volume);
    }
}

 

주의할 점

인터페이스의 모든 메소드는 기본적으로 public 접근 제한을 갖기 때문에 public 보다 더 낮은 접근 제한으로 작성할 수 없다. 만약 인터페이스에 선언된 추상 메소드에 대응하는 실체메소드를 구현 클래스가 작성하지 않으면 구현 클래스는 자동적으로 추상 클래스가 된다. 그렇기 때문에 선언부에 abstract 키워드를 추가해야 한다.

public abstract class Television implements RemoteControl {
	public void turnOn() {...} // setVolume() 실체 메소드가 없다
	public void turnOff() {...}
}

다중 인터페이스 구현 클래스

public class 구현클래스명 implements 인터페이스A, 인터페이스B {
	//인터페이스 A에 선언된 추상 메소드의 실체 메소드 선언
    //인터페이스 B에 선언된 추상 메소드의 실체 메소드 선언
}
public class SmartTelevision implements RemoteControl, Searchable {
	
	private int volume;
	
	@Override
	public void turnOn() {
		System.out.println("TV를 켭니다.");
	}

	@Override
	public void turnOff() {
		System.out.println("TV를 끕니다.");
	}
	
	@Override
	public void setVolume(int volume) {
		if(volume > RemoteControl.MAX_VOLUME) {
			this.volume = RemoteControl.MAX_VOLUME;
		}
		else if(volume < RemoteControl.MIN_VOLUME){
			this.volume = RemoteControl.MIN_VOLUME;
		}
		else {
			this.volume = volume;
		}
		System.out.println("현재 TV 볼륨: " + volume);
	}
	
	@Override
	public void search(String url) {
		System.out.println(url + "을 검색합니다.");
	}

}

 

디폴트 메소드 사용

package 디폴트메소드선언;

public class Audio implements RemoteControl {

	//필드
	private int volume;
	private boolean mute;
	
	@Override
	public void turnOn() {
		System.out.println("Audio를 켭니다.");
	}

	@Override
	public void turnOff() {
		System.out.println("Audio를 끕니다.");
	}

	@Override
	public void setVolume(int volume) {
		if(volume > RemoteControl.MAX_VOLUME) {
			this.volume = RemoteControl.MAX_VOLUME;
		}
		else if(volume < RemoteControl.MIN_VOLUME){
			this.volume = RemoteControl.MIN_VOLUME;
		}
		else {
			this.volume = volume;
		}
		System.out.println("현재 Audio 볼륨: " + volume);
	}
	
	@Override //디폴트 메소드 재정의
	public void setMute(boolean mute) {
		this.mute = mute;
		if(mute) {
			System.out.println("Audio 무음 처리합니다.");
		}
		else {
			System.out.println("Audio 무음 해제합니다.");
		}
	}
	
}