안녕하세요, 스코리아입니다.
오늘은 자바 인터페이스의 의미와 특징, 선언, 구현 방법에 대해서 알아보겠습니다.
인터페이스 의미와 역할
- 개발 코드와 객체가 서로 통신하는 접점
- 개발 코드는 객체의 내부 구조를 알 필요가 없고 인터페이스의 메소드만 알고 있으면 됨
- 개발코드가 객체를 종속되지 않게 하여 객체를 교체할 수 있음
- 개발 코드 변경 없이 리턴값 또는 실행 내용이 다양해짐 (다형성)
인터페이스 특징
- 인터페이스의 모든 메소드는 추상 메소드로 선언됨 (public abstract)
- 인터페이스의 모든 변수는 상수로 선언됨 (public static final)
인터페이스 선언
우선 인터페이스를 선언하는 방법은 다음과 같습니다.
public interface 인터페이스명{
// 인터페이스
}
인터페이스에는 상수 필드, 디폴트 메소드, 추상 메소드, 정적 메소드를 선언할 수 있습니다.
하나씩 살펴보겠습니다.
(1) 상수 필드 선언
- 인터페이스에는 필드 중에 '상수 필드'만 선언 가능 (데이터를 저장하지 않기 때문에 데이터를 저장할 인스턴스 또는 정적 필드가 필요 없음)
- 즉, 인터페이스에 선언된 필드는 모두 public static final 특징을 가짐
- 상수명은 대문자로 작성 (예시: int MAX_VALUE = 10;)
- 선언과 동시에 초기값을 지정해주어야 한다.
- [public static final] 타입상수명 = 값; (public static final 생략해도 됨)
(2) 추상 메소드 선언
- 인터페이스를 통해 호출된 메소드는 최종적으로 객체에서 실행
- 인터페이스의 메소드는 기본적으로 실행 블록이 없는 추상 메소드(abstract method)로 선언
- 개발 코드 -> 인터페이스 (추상메소드: 메소드 선언과 호출 방법만 기술) -> 객체 (재정의된 메소드 : 실제 실행 메소드)
- [public abstract] 리턴타입 메소드명(매개변수, ...); (public abstract 생략해도 됨)
(3) 디폴트 메소드 선언
- 자바 8에서 추가된 인터페이스의 새로운 멤버
- 실행 블록을 가지고 있는 메소드
- [public] default 리턴타입 메소드명(매개변수, ...){ ... } (public 생략해도 됨)
(4) 정적 메소드 선언
- 자바 8에서 추가된 인터페이스의 새로운 멤버
- [public] static 리턴타입 메소드명(매개변수, ...) {... } (public 생략해도 됨)
구현 객체와 구현 클래스
- 인터페이스의 추상 메소드에 대한 실체 메소드를 가진 객체를 '구현 객체'라고 한다.
- 구현 객체를 생성하는 클래스를 '구현 클래스'라고 한다.
- 개발 코드 -> 인터페이스 -> 객체 (구현 객체)
인터페이스 구현과 실체 메소드 작성
- 인터페이스 구현을 위해 자신의 객체가 인터페이스 타입으로 사용할 수 있음을 'implements' 키워드로 명시
public class 구현클래스명 implements 인터페이스명 {
// 인터페이스에 선언된 추상 메소드의 실체 메소드 구현
}
- 메소드의 선언부가 정확히 일치해야 함
- 인터페이스의 '모든' 추상 메소드를 재정의하는 실체 메소드를 작성해야 함 (일부만 재정의할 경우, 추상 abstract 클래스로 선언)
- 인터페이스의 모든 메소드는 public 접근 제한을 갖기 때문에 public보다 더 낮은 접근제한으로 작성할 수 없음
- 인텔리제이 메소드 오버라이딩 단축키: CMD + O
- @Override 어노테이션을 이용해서 정확하게 재정의 되었는지 컴파일러가 체크토록 한다.
RemoteControl rc = new Television();
// 인터페이스클래스이름 변수이름 = 구현 객체
예시와 함께 살펴보기
RemoteControl 인터페이스를 생성하기 위해 RemoteControl.java 파일을 만들고 다음과 같이 작성합니다.
public interface RemoteControl {
/** 상수 필드
- 상수는 무조건 대문자로 작성, 값을 무조건 지정해야함
- public static final이 자동으로 붙음
*/
int MAX_VOLUME = 10;
int MIN_VOLUME = 0;
/** 추상 메소드
- public abstract이 자동으로 붙음
- 선언만 하면 됨. 구현X
*/
void turnOn();
void turnOff();
void setVolume(int volume);
/** 디폴트 메소드
- public이 자동으로 붙음, default는 붙여야함
- 실행블록을 가지고 있음
*/
default void setMute(boolean mute) {
if (mute) {
System.out.println("무음 처리합니다.");
}else{
System.out.println("무읍 해제합니다.");
}
}
/** 정적 메소드
- public이 자동으로 붙음
*/
static void changeBattery() {
System.out.println("건전지를 교환합니다.");
}
}
RemoteControl 인터페이스를 구현하는 Audio 클래스를 생성하기 위해 Audio.java 파일을 만들고 다음과 같이 작성합니다.
public class Audio implements RemoteControl {
private int volume;
private boolean mute;
@Override
public void turnOn() {
System.out.println("오디오를 켭니다.");
}
@Override
public void turnOff() {
System.out.println("오디오를 끕니다.");
}
@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("현재 오디오 볼륨 : " + this.volume);
}
// 디폴트 메소드 재정의
@Override
public void setMute(boolean mute) {
this.mute = mute;
if (mute) {
System.out.println("오디오 무음 처리합니다.");
}else{
System.out.println("오디오 무음 해제합니다.");
}
}
}
RemoteControl 인터페이스를 구현하는 Television 클래스를 생성하기 위해 Television.java 파일을 만들고 다음과 같이 작성합니다.
public class Television implements RemoteControl {
private int volume;
@Override
public void turnOn() {
System.out.println("티비를 켭니다.");
}
@Override
public void turnOff() {
System.out.println("티비를 끕니다.");
}
@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("현재 티비 볼륨 : " + this.volume);
}
}
RemoteControl 인터페이스의 구현 클래스인 Audio와 Television를 사용해 보기 위해 RemoteControlExample.java 파일을 만들고 다음과 같이 작성합니다.
public class RemoteControlExample {
public static void main(String[] args) {
// 인터페이스 사용
RemoteControl rc = null;
rc = new Television(); // 구현 객체를 인터페이스에 대입
rc.turnOn(); // 구현 객체의 추상 메소드
rc.turnOff();
rc = new Audio(); // 구현 객체를 인터페이스에 대입
rc.turnOn(); // 구현 객체의 추상 메소드
rc.turnOff();
// 구현 객체의 디폴트 메소드 (구현 클래스에서 오버라이딩 가능)
rc.setMute(true); // 구현 객체가 인터페이스에 대입된 후 사용 가능
// RemoteControl.setMute(true); -> 불가능
// 구현 객체의 정적 메소드 (인터페이스로 직접 호출 가능)
RemoteControl.changeBattery();
}
}
- RemoteControl 인터페이스에 구현 객체인 Television과 Audio를 각각 대입한 후, 추상메소드인 turnOn과 turnOff를 호출해 보았습니다.
- 구현 객체의 디폴트 메소드를 사용했을때 특징은 다음과 같습니다.
- 인터페이스만으로는 사용 불가 (RemoteControl.setMute(true);와 같이 호출 불가)
- 즉, 구현 객체가 인터페이스에 대입되어야 호출될 수 있는 인스턴스 메소드 (RemoteControl rc = new Television();)
- 모든 구현 객체가 가지고 있는 기본 메소드로 사용
- 필요에 따라 구현 클래스가 디폴트 메소드를 재정의해서 사용 가능 (Audio 클래스처럼)
- 디폴트 메소드를 추가하더라도 기존 구현 클래스들은 문제없이 사용 가능
- 디폴트 메소드가 있는 인터페이스 상속 방법: 부모 인터페이스의 디폴트 메소드를 자식 인터페이스에서 활용하기
- 디폴트 메소드를 단순히 상속
- 디폴트 메소드를 재정의(Override)해서 실행 내용 변경
- 디폴트 메소드를 추상 메소드로 선언 (구현 클래스에서 재정의해야 함)
- 구현 객체의 정적 메소드를 사용했을 때 특징은 다음과 같습니다.
- 인터페이스로 직접 호출 가능 (static 이므로)
- RemoteControl.changeBattery(); 를 예시로 들 수 있음.
지금까지 자바(Java) 인터페이스의 의미와 특징, 선언, 구현 방법에 대해서 알아보았습니다.
읽어주셔서, 감사합니다.
'JAVA > 객체지향' 카테고리의 다른 글
자바 추상클래스 의미, 구현 방법 (abstract class) (2) | 2023.09.08 |
---|---|
자바 강제타입변환(다운케스팅 형변환) 의미, 사용방법 (2) | 2023.09.06 |
자바 다형성 의미, 사용방법 (feat.객체지향) (1) | 2023.09.02 |
자바 메소드 재정의 의미, 사용방법 (@Override) (2) | 2023.08.31 |
자바 자동타입변환(업케스팅 형변환) 의미, 사용 방법 (2) | 2023.08.29 |