: 개발 코드와 객체가 서로 통신하는 접점 역할
: 하나의 객체가 아니라 여러 객체들과 사용이 가능
: 개발 코드 측면에서는 코드 변경 없이
실행 내용과 리턴값을 다양화할 수 있다는 장점을 가짐
: 개발 코드가 인터페이스의 메소드를 호출하면
인터페이스는 객체의 메소드를 호출시킴
→ 개발 코드는 객체의 내부 구조를 알 필요가 없고
인터페이스의 메소드만 알고 있으면 됨
: 개발 코드가 직접 객체의 메소드를 호출하면 간단한데
왜 중간에 인터페이스를 두는지 의문
→ 개발 코드를 수정하지 않고 사용하는 객체를
변경할 수 있도록 하기 위해서
[public] interface 인터페이스이름 { ··· }
interface 인터페이스이름 {
//상수
타입 상수이름 = 값;
//추상 메소드
타입 메소드이름(매개변수, ···)
}
- 구성 멤버 [클래스 vs 인터페이스]
* 클래스 : 필드, 생성자, 메소드
* 인터페이스: 상수필드, 추상 메소드
→ 인터페이스는 객체로 생성할 수 없기 때문에
생성자를 가질 수 없음
- 상수 필드 선언
[public statci final] 타입 상수이름 = 값;
: public static final을 생략하더라도 컴파일 과정에서 자동으로 붙게 됨
: 인터페이스는 객체 사용 방법을 정의한 것으로
실행 시 데이터를 저장할 수 있는 인스턴스 또는 정적 필드를 선언할 수 없음
: 상수 필드는 선언이 가능함, 상수는 인터페이스에 고정된 값으로
실행 시에 데이터를 바꿀 수 없음
public interface RemoteControl {
public int MAX_VOLUME = 10;
public int MIN_VOLUME = 0;
}
- 추상 메소드 선언
[public abstract] 리턴타입 메소드이름(매개변수, ···);
: 인터페이스로 호출된 메소드는 객체에서 실행되므로
추상 메소드로 선언함
: 인터페이스에 선언된 추상 메소드는
모두 Public Abstract의 특성을 갖기 때문에 생략하더라도
컴파일 과정에서 자동으로 붙게 됨
public interface RemoteControl {
//상수
public int MAX_VOLUME = 10;
public int MIN_VOLUME = 0;
//추상 메소드
//메소드 선언부만 작성
public void turnOn();
public void turnOff();
public void setVolume(int volume);
}
: 개발 코드 → 인터페이스 메소드 호출
: 인터페이스 메소드 → 객체의 메소드 호출
: 객체는 인터페이스에서 정의된 추상 메소드와 동일한
메소드 이름, 매개 타입, 리턴 타입을 가진 실체 메소드를 가지고 있어야함
: 이러한 객체를 인터페이스의 구현객체라고 하고,
구현 객체를 생성하는 클래스를 구현 클래스 라고 함
- 구현 클래스
public class 구현클래스 이름 implements 인터페이스이름 {
//인터페이스에 선언된 추상 메소드의 실체 메소드 선언
}
: 인터페이스 타입으로 사용할 수 있음을 알려주기 위해
클래스 선언부에 implements 키워드를 추가하고
인터페이스 이름을 명시해야함
: 인터페이스에 선언된 추상 메소드의 실체 메소드를 선언해야함
public class Television implements RemoteControl{
//필드
private int volume;
//turnOn() 추상 메소드의 실체 메소드
public void turnOn(){
System.out.println("Television를 켭니다");
}
//turnOff() 추상 메소드의 실체 메소드
public void turnOff(){
System.out.println("Television를 끕니다.");
}
@Override
//setVolume() 추상 메소드의 실체 메소드
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("현재 Television 볼륨: " + this.volume);
}
}
public class Audio implements RemoteControl{
//필드
private int volume;
//turnOn() 추상 메소드의 실체 메소드
public void turnOn(){
System.out.println("Audio를 켭니다");
}
//turnOff() 추상 메소드의 실체 메소드
public void turnOff(){
System.out.println("Audio를 끕니다.");
}
@Override
//setVolume() 추상 메소드의 실체 메소드
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 생략 불가능
→ 구현 클래스가 작성되면 new 연산자로 객체 생성 가능
1)
인터페이스 변수;
변수 = 구현객체;
2)
인터페이스 변수 = 구현객체;
: 인터페이스로 구현 객체를 사용하려면
인터페이스 변수를 선언하고
구현 객체를 대입해야함
: 인터페이스 변수는 참조 타입이기 때문에
구현 객체가 대입될 경우 구현 객체의 번지를 저장해야함
public class RemoteControlExample{
public static void main(String[] args){
RemoteControl rc;
rc = new Television();
rc = new Audio();
}
}
- 다중 인터페이스 구현 클래스
public class 구현클래스이름 implements 인터페이스A, 인터페이스B {
//인터페이스 A에 선언된 추상 메소드의 실체 메소드 선언
//인터페이스 B에 선언된 추상 메소드의 실체 메소드 선언
}
: 구현 클래스는 모든 인터페이스의
추상 메소드에 대해 실체 메소드를 작성해야함
/* 인터페이스 */
//인터넷을 검색할 수 있는 Searchable 인터페이스
//search()추상 메소드는 매개값으로
//인터넷 웹사이트 주소(URL)를 받는다.
public interface Searchable {
void search(String url);
}
/* 다중 인터페이스 구현 클래스 */
//SmartTelevision이 인터넷 검색 기능도 제공한다면
//RemoteControl과 Searchable을 모두 구현한
//SmartTelevision 클래스를 작성할 수 있음
public class SmartTelevision implements RemoteControl, Searchable {
//필드
private int volume;
// RemoteControl의 추상 메소드에 대한 실체 메소드
public void turnOn(){
System.out.println("Audio를 켭니다");
}
public void turnOff(){
System.out.println("Audio를 끕니다.");
}
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);
}
//Searchable의 추상 메소드에 대한 실체 메소드
public void search(String url){
System.out.println(url + "을 검색합니다.");
}
}
/* 인터페이스 변수에 구현 객체 대입 */
// SamrtTelevision 클래스는 RemoteControl과 Searchable 인터페이스를
// 모두 구현하고 있기 떄문에
// SmartTelevision 객체를 RemoteControl타입 변수과
// Searchable 타입 변수에 각각 대입할 수 있음
public class SmartTelevisionExample {
public static void main(String[] args){
SmartTelevision tv = new SmartTelevision();
RemoteControl rc = tv;
Searchable searchable = tv;
}
}
: 클래스를 선언할 때 인터페이스는 필드, 생성자 또는
메소드의 매개 변수, 생성자 또는 메소드의 로컬 변수로 선언 가능
ex)
RemoteControl 인터페이스를 필드, 생성자 또는
메소드의 매개 변수 그리고 메소드의 로컬 변수로 선언함
public class MyClass{
//필드
1. RemoteControl rc = new Television();
//생성자
2. MyClass(RemoteControl rc){
this.rc = rc;
]
//메소드
void methodA() {
//로컬 변수
3.RemoteControl rc = new Audio();
}
//생성자의 매개값으로 구현 객체 대입
//mc.methodB(new Audio());
4.void methodB(RemoteControl rc){ ··· }
}
1. 인터페이스가 필드 타입으로 사용될 경우,
필드에 구현 객체를 대입할 수 있음
//구현 객체가 인터페이스 타입에 대입되면
//인터페이스에 선언된 추상 메소드를
//개발 코드에서 사용할 수 있게 됨
//개발 코드에서 RemoteControl의 변수 rc로
//trunOn() 또는 turnOff()메소드를 호출하면
//구현 객체의 turnOn()과 turnOff()메소드가 자동 실행됨
- MyClass myClass = new MyClass();
myClass.rc.turnOn(); //Television의 turnOn()이 실행
myClass.rc.setVolume(5); //Televisiont의 setVolumn(5)가 실행
2. 인터페이스가 생성자의 매개 변수 타입으로 사용될 경우,
new연산자로 객체를 생성할 때 구현 객체를
생성자의 매개값으로 대입할 수 있음
MyClass(RemoteControl rc){
this.rc = rc;
rc.turnOn();
rc.setVolume(5)
3. 인터페이스가 로컬 변수 타입으로 사용될 경우,
변수에 구현 객체를 대입할 수 있음
void mehodA() {
RemoteControl rc = new Audio();
rc.turnOn();
rc.setVolume(5);
}
4. 인터페이스가 메소드의 매개 변수 타입으로 사용될 경우,
메소드 호출 시 구현 객체를 매개값으로 대입 가능
void methodB(RemoteControl rc){
rc.turnOn();
rc.setVolume(5);
}
→ methodB()가 호출되었을 경우
Television의 turnOn과 setVolume()메소드가 실행됨
MyClass myClass = new myClass();
myClass.methodB(new Television());
/* 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) {
System.out.println("1)-------------");
MyClass myClass1 = new MyClass();
myClass1.rc.turnOn();
myClass1.rc.setVolume(5);
System.out.println("2)-------------");
MyClass myClass2 = new MyClass(new Audio());
System.out.println("3)-------------");
MyClass myClass3 = new MyClass();
myClass3.methodA();
System.out.println("4)-------------");
MyClass myClass4 = new MyClass();
myClass4.methodB(new Television());
}
}
💻 결과
1)-------------
Television를 켭니다
현재 Television 볼륨: 5
2)-------------
Audio를 켭니다
현재 Audio 볼륨: 5
3)-------------
Audio를 켭니다
현재 Audio 볼륨: 5
4)-------------
Television를 켭니다
현재 Television 볼륨: 5