○ 인터페이스의 디폴트 메서드 사용
디폴트 메서드는 인터페이스의 모든 인스턴스가 자동으로 보유하게 되는 말 그대로 '기본' 메서드입니다. 별다른 오버라이드 없이도, 기본적인 추상 메서드 구현만 잘 이루어졌다면 특별한 구현 클래스에서의 작업 없이 사용이 가능하죠. 실행 코드는 이미 인터페이스 상에 선언이 되어 있습니다. 물론, 엄격하게 구조를 따지면 인터페이스 상에 실행 코드가 정의되어 있긴 하지만 - 실제로는 구현 클래스 인스턴스가 보유하고 있는 구조라고 생각해야 합니다.
그리고 위의 문장에서 구현 클래스의 인스턴스가 보유하는 메서드라고 말했습니다. 이 부분을 강조하는 이유는 무엇일까요? 그건 인터페이스에 실행 코드가 선언되어 있긴 하지만, 반드시 구현 클래스 인스턴스를 통해서만 실행이 가능한 메서드이기 때문입니다. 이것이 인터페이스 정적(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();
}
}
'Programming > JAVA' 카테고리의 다른 글
인터페이스(8) - 인터페이스의 타입 변환과 다형성 2 (0) | 2023.03.24 |
---|---|
인터페이스(8) - 인터페이스의 타입 변환과 다형성 1 (0) | 2023.03.23 |
인터페이스(7) - 인터페이스의 구현과 사용 1 : 추상 메서드 사용 (0) | 2023.03.22 |
인터페이스(6) - 인터페이스 구현 : 다중 인터페이스 구현 (0) | 2023.03.20 |
인터페이스(5) - 인터페이스 구현 : 익명 객체의 구현 (0) | 2023.03.20 |