8.4 추상 메소드
- 인터페이스는 구현 클래스가 재정의해야 하는 public 추상 메소드를 멤버로 가질 수 있음
* 추상 메소드 : 리턴 타입, 메소드명, 매개변수만 기술/ 중괄호 {}를 붙이지 않는 메소드
- public abstract를 생략하더라도 컴파일 과정에서 자동으로 붙게 됨
=> 객체 A가 인터페이스를 통해 어떻게 메소드를 호출할 수 있는지 방법을 알려주는 역할을 함
(인터페이스 구현 객체 B는 추상 메소드의 실행부를 갖는, 재정의된 메소드가 있어야 함)
객체 A | -- 메소드 호출 --> | 인터페이스 | -- 메소드 호출 --> | 객체 B |
<-- 리턴값 -- | <-- 리턴값 | |||
추상 메소드 (메소드 선언부) (호출 방법만 기술) |
재정의된 메소드 (실제 실행 코드를 가지고 있는 메소드) |
[public abstract] 리턴타입 메소드명(매개변수, ...);
public interface RemoteControl {
//상수 필드
int MAX_VOLUME = 10;
int MIN_VOLUMT = 0;
//추상 메소드
// 메소드 선언부만 작성!!
void turnOn();
void turnOff();
void setVolume(int volume);
}
- 구현 클래스들은 인터페이스에 선언된 모든 추상 메소드를 재정의해 실행 코드를 가져야 함
public class Television implements RemoteControl {
//필드
private int volume;
//turnOn() 추상 메소드 오버라이딩
@Override
public void turnOn() {
System.out.println("TV를 켭니다.");
}
//turnOff() 추상 메소드 오버라이딩
@Override
public void turnOff() {
System.out.println("TV를 끕니다.");
}
//setVolume() 추상 메소드 오버라이딩
@Override
public void setVolume(int volume) {
//인터페이스 상수 필드를 이용해 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 볼륨 : " + this.volume);
}
}
public class Audio implements RemoteControl {
//필드
private int volume;
//turnOn() 추상 메소드 오버라이딩
@Override
public void turnOn() {
System.out.println("Audio를 켭니다.");
}
//turnOff() 추상 메소드 오버라이딩
@Override
public void turnOff() {
System.out.println("Audio를 끕니다.");
}
//setVolume() 추상 메소드 오버라이딩
@Override
public void setVolume(int volume) {
//인터페이스 상수 필드를 이용해 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 볼륨 : " + this.volume);
}
}
* 구현 클래스에서 추상 메소드를 재정의할 때 주의할 점
: 인터페이스의 추상 메소드는 기본적으로 public 접근 제한을 가짐 --> public보다 더 낮은 접근 제한으로 재정의 불가
=> 재정의되는 메소드에는 모두 public이 추가되어 있음
public class RemoteControlExample {
public static void main(String[] args) {
//인터페이스 변수 선언
RemoteControl rc;
//Television 객체를 생성, 인터페이스 변수에 대입
// 인터페이스로 Television 객체 사용
rc = new Television();
rc.turnOn();
rc.setVolume(5);
rc.turnOff();
}
}
8.5 디폴트 메소드
- 인터페이스에는 완전한 실행 코드를 가진 디폴트 메소드를 선언할 수 있음
* 디폴트 메소드 : 실행부 (중괄호 { })가 있음
- 실행부에는 상수 필드를 읽거나 추상 메소드를 호출하는 코드를 작성할 수 있음
- 디폴트 메소드는 구현 객체가 필요한 메소드임
-> 구현 객체를 인터페이스 변수에 대입한 뒤에 해당 메소드를 호출해야 함 ( . 연산자 사용)
- 선언 방법 : 클래스 메소드와 동일, but default 키워드가 리턴 타입 앞에 붙음
[public] default 리턴타입 메소드명(매개변수, ...) {...}
public interface RemoteControl {
//상수 필드
int MAX_VOLUME = 10;
int MIN_VOLUMT = 0;
//추상 메소드
// 메소드 선언부만 작성!!
void turnOn();
void turnOff();
void setVolume(int volume);
//디폴트 인스턴스 메소드
default void setMute(boolean mute) {
if(mute) {
System.out.println("무음 처리됩니다.");
//추상 메소드 호출하면서 상수 필드를 사용함.
setVolume(MIN_VOLUME);
} else {
System.out.println("무음 해제합니다.");
}
}
}
public class RemoteControlExample {
public static void main(String[] args) {
//인터페이스 변수 선언
RemoteControl rc;
//Television 객체를 생성, 구현 객체를 인터페이스 변수에 대입
// 인터페이스로 Television 객체 사용
rc = new Television();
rc.turnOn();
rc.setVolume(5);
//디폴트 메소드 호출
rc.setMute(true);
rc.setMute(false);
}
}
- 구현 클래스는 디폴트 메소드를 재정의해 자신에게 맞게 수정 가능!
* public 접근 제한자를 반드시 붙여야 함
* default 키워드를 생략해야 함
public class Audio implements RemoteControl {
//필드
private int volume;
//turnOn() 추상 메소드 오버라이딩
@Override
public void turnOn() {
System.out.println("Audio를 켭니다.");
}
//turnOff() 추상 메소드 오버라이딩
@Override
public void turnOff() {
System.out.println("Audio를 끕니다.");
}
//setVolume() 추상 메소드 오버라이딩
@Override
public void setVolume(int volume) {
//인터페이스 상수 필드를 이용해 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 볼륨 : " + this.volume);
}
// 추가 필드 선언
private int memoryVolume;
//디폴트 메소드 재정의
@Override
public void setMute(boolean mute) {
if(mute) {
//무음처리하기 전, 저장해두는 부분!
this.memoryVolume = this.volume;
System.out.println("무음 처리합니다.");
setVolume(RemoteControl.MIN_VOLUME);
} else {
System.out.println("무음 해제합니다.");
//mute가 false인 경우, 원래 볼륨으로 복원...
// 무음처리하기 전에 저장해둔 것을 사용해 복원!
setVolume(this.memoryVolume);
}
}
}
8.6 정적 메소드
- 인터페이스에는 정적 메소드도 선언 가능
(추상 메소드, 디폴트 메소드는 구현 객체가 필요)
(정적 메소드는 구현 객체가 없어도 인터페이스만으로 접근해 호출 가능!)
- public을 생략해도, 자동으로 컴파일 과정에서 붙는다
- 정적 메소드의 실행부 (중괄호 { }) 작성 시 주의할 점
* 상수 필드를 제외한 추상 메소드, 디폴트 메소드, private 메소드 등을 호출할 수 없다는 것
(구현 객체가 필요한 인스턴스 메소드들이라서!)
[public | private] static 리턴타입 메소드명(매개변수, ...) {...}
public interface RemoteControl {
//상수 필드
int MAX_VOLUME = 10;
int MIN_VOLUMT = 0;
//추상 메소드
// 메소드 선언부만 작성!!
void turnOn();
void turnOff();
void setVolume(int volume);
//디폴트 인스턴스 메소드
default void setMute(boolean mute) {
if(mute) {
System.out.println("무음 처리됩니다.");
//추상 메소드 호출하면서 상수 필드를 사용함.
setVolume(MIN_VOLUME);
} else {
System.out.println("무음 해제합니다.");
}
}
//정적 메소드, 추가!
static void changeBattery() {
System.out.println("리모컨 건전지를 교환합니다");
}
}
public class RemoteControlExmaple {
public static void main(String[] args) {
//위 코드 생략
//정적 메소드 호출
RemoteControl.changeBattery();
}
}
8.7 pritave 메소드
- private 메소드의 용도 : 디폴트와 정적 메소드들의 중복 코드를 줄이는 것
- 인터페이스의 상수 필드, 추상 메소드, 디폴트 메소드, 정적 메소드는 모두 public 접근 제한을 가짐
(해당 멤버들을 선언할 때에는, 생략 시 public -> 외부에서 접근 가능)
(private 메소드 선언도 가능! -> 외부에서 접근 불가)
private 메소드 | - 구현 객체가 필요함 - 디폴트 메소드 안에서만 호출 가능 |
private 정적 메소드 | - 구현 객체가 필요 없는 메소드 - 디폴트 메소드, 정적 메소드 안에서 호출 가능 |
public interface Service {
//디폴트 메소드
default void defaultMethod1() {
System.out.println("defaultMethod1 종속 코드");
defaultCommon();
}
default void defaultMethod2() {
System.out.println("defaultMethod2 종속 코드");
defaultCommon();
}
//private 메소드
private void defaultCommon() {
System.out.println("defaultMethod 중복 코드A");
System.out.println("defaultMethod 중복 코드B");
}
//정적 메소드
static void staticMethod1() {
System.out.println("staticMethod1 종속 코드");
staticCommon();
}
static void staticMethod2() {
System.out.println("staticMethod2 종속 코드");
staticCommon();
}
//private 정적 메소드
private static void staticCommon() {
System.out.println("staticMethod 중복 코드C");
System.out.println("staticMethod 중복 코드D");
}
}
public class ServiceImpl implements Service {
//추상 메서드가 없으므로 재정의 내용 없음
}
public class ServiceExample {
public static void main(String[] args) {
//인터페이스 변수 선언과 구현 객체 대입
Service service = new ServiceImpl();
//디폴트 메소드 호출
service.defaultMethod1();
System.out.println();
service.defaultMethod2();
System.out.println();
//정적 메소드 호출 - 구현객체 없이!!
Service.staticMethod1();
System.out.println();
Service.staticMethod2();
System.out.println();
}
}
'언어 > java' 카테고리의 다른 글
[Java] 8. 인터페이스 (4) - 11~13 (0) | 2025.05.26 |
---|---|
[Java] 8. 인터페이스 (3) - 8~10 (0) | 2025.05.26 |
[Java] 8. 인터페이스 (1) - 1~3 (0) | 2025.05.22 |
[Java] 7. 상속 (4) - 10~11 (0) | 2025.05.22 |
[Java] 7. 상속 (2) - 5~6 (0) | 2025.05.20 |