08-1 인터페이스
인터페이스는 개발 코드와 객체가 서로 통신하는 접점 역할을 한다.
개발코드가 인터페이스의 메소드를 호출하면 인터페이스는 객체의 메소드를 호출한다.
왜 개발코드가 직접 객체의 메소드를 호출하지 않고 중간에 인터페이스를 둘까?
이유는 개발코드를 수정하지 않고 사용하는 객체를 변경할 수 있도록 하기 위해서 이다. 인터페이스는 여러 객체들과 사용이 가능하므로 어떤 객체를 사용하느냐에 따라 실행 내용과 리턴값이 달라질 수 있는데 개발코드 입장에서는 수정없이 실행 내용과 리턴값을 다양화할 수 있다는 장점이 있다.
인터페이스 선언
인터페이스는 ~.java로 작성되고 컴파일러를 통해 ~.class 로 컴파일되어 물리적 형태는 클래스와 동일하나, 소스를 작성할 때 선언하는 방법이 다르다.
선언부에 interface 키워드를 추가하여 선언한다.
[public] interface 인터페이스이름 {...}
인터페이스 이름은 영어 대소문자를 구분하며, 첫글자 대문자에 나머지는 소문자로 작성하는 것이 관례이다.
+ 인터페이스의 public 접근 제한자는 다른 패키지에서도 인터페이스를 사용할 수 있도록 한다.
- 인터페이스 구성
클래스와 달리 인터페이스는 상수필드와 추상메소드만을 구성 멤버로 가지며, 객체를 생성할 수 없기 때문에 생성자를 가질 수 없다.
interface 인터페이스이름 {
//상수
타입 상수이름 = 값;
//추상메소드
타입 메소드이름(매개변서,...);
}
- 상수 필드 선언
인터페이스는 객체 사용 방법을 정의한 것으로 데이터를 저장할 수 있는 인스턴스 또는 정적 필드를 선언할 수 없다.
단, 상수 필드는 선언이 가능하다.
[public static final] 타입 상수이름 = 값;
상수를 선언하는 public static final을 앞에 붙이지 않아도 인터페이스에 선언딘 필드는 모두 public static final 특성이 붙어 생략하더라도 컴파일 과정에서 자동으로 붙는다. 그리고 인터페이스 상수는 선언과 동시에 초기값을 지정해야한다. (생성자로 넣는 방법이 불가능하기 때문)
상수 이름은 대문자로 작성, 서로 다른 단어로 구성되어 있으면 _로 연결하는 것이 관례이다.
- 추상 메소드 선언
[public abstract] 리턴타입 메소드이름(매개변수, ...);
인터페이스를 통해 호출된 메소드는 최종적으로 객체에서 실행된다. 그래서 인터페이스 메소드는 실행 블록이 없는 추상 메소드로 선언한다. 인터페이스의 메소드는 모두 public abstract 특성을 붙어 이를 생략해도 컴파일 과정에서 자동으로 붙는다.
인터페이스 구현 (implement)
인터페이스에는 실행 블록이 없는 추상 메소드만 가지고 있기 때문에 객체는 인터페이스가 정의한 추상 메소드와 동일한 선언부를 가진 실체 메소드를 가지고 있어야 한다. 이러한 객체를 인터페이스의 구현(implement) 객체라 하고, 구현 객체를 생성하는 클래스를 구현 클래스라 한다.
- 구현 클래스
보통의 클래스와 동일한데, 인터페이스 타입으로 사용할 수 있음을 알리기 위해 클래스 선언부에 implements 키워드를 추가한다.
public class 구현클래스이름 implements 인터페이스이름 {
// 인터페이스에 선언된 추상 메소드의 실체 메소드 선언
}
+ 인터페이스 모든 메소드들은 기본적으로 public 접근 제한을 갖기에 구현 클래스 역시 public 보다 낮은 접근 제한을 작성할 수 없다.
구현 클래스가 작성되면 new 연산자로 객체를 생성할 수 있지만 일반적인 클래스처럼 클래스 변수에 대입하는 것으로는 인터페이스를 사용할 수 없다. 클래스 변수가 아닌 인터페이스 변수를 선언하고 대입해야 한다.
인터페이스 변수;
변수 = 구현 객체;
// or
인터페이스 변수 = 구현 객체;
- 다중 인터페이스 구현 클래스
객체는 다수의 인터페이스를 implements 선언하여 다수의 인터페이스의 타입으로 사용할 수 있다. 다만, 인터페이스 각각의 추상 메소드를 한 객체 안에 모두 구현해야 한다.
public class 구현클래스이름 implements A인터페이스이름, B인터페이스이름 {
// 인터페이스 A에 선언된 추상 메소드의 실체 메소드 선언
// 인터페이스 B에 선언된 추상 메소드의 실체 메소드 선언
}
그리고 둘 모두 구현하고 있어 각각 인터페이스 변수에 대입이 가능하다.
A인터페이스 변수 = 구현객체;
B인터페이스 변수 = 구현객체;
- 인터페이스 사용
인터페이스는 클래스를 선언할 때 다음과 같은 용도들로 선언될 수 있다.
- 필드
- 생성자의 매개변수
- 메소드의 매개변수
- 생성자의 로컬 변수
- 메소드의 로컬 변수
- 인터페이스 사용 예시
인터페이스 RemoteControl.java
public interface RemoteControl {
// public static final 키워드 자동 붙음
public int MAX_VOLUME = 10;
public int MIN_VOLUME = 0;
// public abstract 키워드 자동 붙음
public void turnOn();
public void turnOff();
public void setVolume(int volume);
}
구현클래스1 Television.java
public class Television implements RemoteControl {
private int volume;
public void turnOn(){
System.out.println("TV를 켭니다.");
}
public void turnOff(){
System.out.println("TV를 끕니다.");
}
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 볼륨 : " + this.volume);
}
}
구현클래스2 Audio.java
public class Audio implements RemoteControl {
private int volume;
public void turnOn(){
System.out.println("Audio를 켭니다.");
}
public void turnOff(){
System.out.println("Audio를 끕니다.");
}
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 볼륨 : " + this.volume);
}
}
인터페이스 사용 MyClass.java
public class MyClass {
//필드로 사용
RemoteControl rc = new Television();
MyClass(){
}
//생성자 매개변수로 사용
MyClass(RemoteControl rc){
this.rc = rc
rc.turnOn();
rc.setVolume(5);
}
//메소드의 로컬변수로 사용
void methodA (){
RemoteControl rc = new Audio();
rc.turnOn();
rc.setVolume(5);
}
//메소드의 매개변수로 사용
void methodB (RemoteControl rc){
rc.turnOn();
rc.setVolume(5);
}
}
인터페이스 사용 MyClassExample.java
public class MyClassExample{
public static void main(String[] args){
// 기본 생성자로 생성되어 클래스 선언때 선언한 tv객체를 참조한 필드를 사용
MyClass myClass1 = new MyClass();
myClass1.rc.turnOn(); // TV를 켭니다.
myClass1.rc.setVolume(4); // 현재 TV 볼륨 : 4
// 매개값있는 생성자로 생성되어 매개값으로 던진 Audio객체를 사용, 생성자 안의 메소드까지 실행
MyClass myClass2 = new MyClass(new Audio());
// Audio를 켭니다.
// 현재 Audio 볼륨 : 5
// 클래스 안의 methodA 메소드를 실행
MyClass myClass3 = new MyClass();
myClass3.methodA();
// Audio를 켭니다.
// 현재 Audio 볼륨 : 5
// 클래스 안의 methodB 메소드를 실행
MyClass myClass4 = new MyClass();
myClass4.methodB(new Television);
// TV를 켭니다.
// 현재 TV 볼륨 : 5
}
}
추상 클래스랑 인터페이스랑 뭐가 다르지?
추상클래스는 extend의 단어 뜻대로 자신의 기능을 하위로 확장 시키는 개념에 가깝다고 한다면
인터페이스는 implement 단어 뜻대로 인터페이스에 정의된 메서드를 각 클래스의 목적 혹은 성능에 맞게 동일한 기능으로 구현하는 것으로 볼 수 있다.
추상 클래스는 extends 키워드를 사용하며 다중 상속이 불가능
인터페이스는 implements 키워드를 사용하며 다중 상속이 가능하다.
정리하자면 자바의 특성상 한 개의 클래스만 상속이 가능하기 때문에 해당 클래스의 구분을 추상 클래스 상속을 통해서 해결하고, 할 수 있는 공통된 기능들을 인터페이스의 다중 상속을 통해 구현하는 식으로 사용
+ 추상화 정도는 일반 메서드 일반 멤버 변수, 생성자를 가질수 없는 인터페이스가 더 높다

자바 추상 클래스와 인터페이스의 차이점 이해하기
'is a kind of(~의 한 종류) 추상 클래스'와 'be able to(~할 수 있는) 인터페이스' - 추상 클래스 public abstract class 클래스이름 { ... public abstract void 메서드이름(); } class 앞에 'abstract' 키워드를 사용하여 정
wildeveloperetrain.tistory.com
'Programming > Java' 카테고리의 다른 글
| 혼공자바] 09-1 중첩 클래스와 중첩 인터페이스 소개 (0) | 2022.12.09 |
|---|---|
| 혼공자바] 08-2 인터페이스 타입 변환과 다형성 (1) | 2022.12.06 |
| 혼공자바] 07-3 추상 클래스 (1) | 2022.12.03 |
| 혼공자바] 07-2 클래스 타입 변환과 다형성 (0) | 2022.12.02 |
| 혼공자바] 07-1 상속 (0) | 2022.11.30 |
