본문 바로가기

Programming/JAVA

인터페이스(7) - 인터페이스의 구현과 사용 2 : 디폴트, 정적 메서드

java logo image

 

 

 

○ 인터페이스의 디폴트 메서드 사용

 

디폴트 메서드는 인터페이스의 모든 인스턴스가 자동으로 보유하게 되는 말 그대로 '기본' 메서드입니다. 별다른 오버라이드 없이도, 기본적인 추상 메서드 구현만 잘 이루어졌다면 특별한 구현 클래스에서의 작업 없이 사용이 가능하죠. 실행 코드는 이미 인터페이스 상에 선언이 되어 있습니다. 물론, 엄격하게 구조를 따지면 인터페이스 상에 실행 코드가 정의되어 있긴 하지만 - 실제로는 구현 클래스 인스턴스가 보유하고 있는 구조라고 생각해야 합니다. 

 

그리고 위의 문장에서 구현 클래스의 인스턴스가 보유하는 메서드라고 말했습니다. 이 부분을 강조하는 이유는 무엇일까요? 그건 인터페이스에 실행 코드가 선언되어 있긴 하지만, 반드시 구현 클래스 인스턴스를 통해서만 실행이 가능한 메서드이기 때문입니다. 이것이 인터페이스 정적(static) 메서드와의 차이점이자 사용 시 주의사항입니다. 

 

public interface RemoteControl {
    public int MAX_VOLUME = 10;
    public int MIN_VOLUME = 0;
    
    public void turnOn();
    public void turnOff();
    public void setVolume(int volume);
    
    default void setMute(boolean mute) {
        if(mute) {
            System.out.println("무음");
        } else {
            System.out.println("무음 해제");
        }
    }
    
    static void changeBattery() {
        System.out.println("배터리 교환");
    }
}

 

위의 setMute(boolean mute)가 바로 디폴트 메서드입니다. 메서드에 키워드 default가 포함되어 있죠? 이 메서드를 실행 클래스에서 사용한다고 가정하면 다음과 같습니다.

 

RemoteControl rc = new Television();
rc.setMute(true);

RemoteControl.setMute(true)   // 사용 불가

 

 

물론, 디폴트 메서드 역시 구현 클래스에서 오버라이드하여 필요에 맞게 사용할 수 있습니다. RemoteControl 인터페이스를 Television과 Audio에서 각각 구현하여 실행하되 디폴트 메서드인 setMute( )를 Audio에서 오버라이드 해보고 이를 실행하겠습니다. 

 

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 class Audio implements RemoteControl {
	// 필드
	private int volume;
	private boolean mute;
	
	// turnOn() 추상 메서드의 실체 메서드
	public void turnOn() {
		System.out.println("스피커를 켭니다.");
	}
	
	// turnOff() 추상 메서드의 실체 메서드
	public void turnOff() {
		System.out.println("스피커를 끕니다.");
	}
	
	// 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("현재 스피커 볼륨: " + volume);
	}
	
	// setMute() 디폴트 메서드 오버라이드
	@Override
	public void setMute(boolean mute) {
        this.mute = mute;
		if(mute) {
            System.out.println("AUDIO 전용 무음");
        } else {
            System.out.println("AUDIO 전용 무음 해제");
        }
	}
}

 

public class ExampleMain {	
	public static void main(String[] args) {
		RemoteControl rc = null;
		
		rc = new Television();
		rc.turnOn();
		rc.setMute(true);
		
		rc = new Audio();
		rc.turnOn();
		rc.setMute(true);
	}
}

/* 출력
TV를 켭니다.
무음
스피커를 켭니다.
AUDIO 전용 무음
*/

 

 


 

 

○ 인터페이스의 정적 메서드 사용

 

인터페이스에 정의된 정적 메서드는 다음과 같이 별다른 구현 클래스 인스턴스 없이, 인터페이스를 통해 직접 호출이 가능합니다. 우리가 익히 배워온 static 메서드의 개념을 빗대어 생각하시면 간단히 이해할 수 있습니다. 

 

public class ExampleMain {	
	public static void main(String[] args) {
		RemoteControl rc = null;
		
		rc = new Television();
		rc.turnOn();
		rc.setMute(true);
		
		rc = new Audio();
		rc.turnOn();
		rc.setMute(true);
		
		RemoteControl.changeBattery();
	}
}