인터페이스_인터페이스
1. 인터페이스
인터페이스는 객체의 사용 방법을 정의한 타입이며, 개발 코드와 객체가 서로 통신하는 매개체 역할을 한다.
만약 개발 코드가 인터페이스의 메소드를 호출하면, 인터페이스는 객체의 메소드를 호출한다. 이 때문에 개발 코드는 객체의 내부 구조를 알 필요가 없으며, 인터페이스에 대해서만 알고 있으면 된다.
인터페이스를 사용하는 이유는 개발의 효율성 때문이다.
인터페이스를 사용하면 개발 코드를 수정하지 않고 사용하는 객체를 변경할 수 있다.
인터페이스는 여러 객체들을 사용할 수 있으므로, 어떤 객체를 사용하느냐에 따라 실행 내용이 달라질 수 있다.
따라서 개발 코드를 변경하지 않고 실행 내용을 다양화할 수 있다는 장점을 갖게 된다.
2. 인터페이스 선언
인터페이스는 .java 형태로 소스 파일이 작성되고, .class 형태로 컴파일 된다.
따라서 물리적 형태는 클래스와 동일하다.
그러나 class가 아닌 interface 키워드로 선언된다.
- public interface 인터페이스명 {};
클래스는 필드, 생성자, 메소드를 멤버로 가질 수 있다.
그에 반해 인터페이스는 객체로 생성될 수 없기 때문에 생성자를 가질 수 없으며 상수 필드, 추상 메소드만을 멤버로 가질 수 있다.
1) 상수 필드 선언
인터페이스는 객체의 사용 방법만을 정의해둔 것이므로, 실제 데이터를 저장할 수 있는 인스턴스 또는 정적 필드를 선언할 수 없다.
앞에서 상수는 public static final의 특성을 가진다는 것을 배웠다.
따라서 인터페이스에 선언된 필드는 public static final의 특성을 가지며, 선언 시에 생략하더라도 컴파일 과정에서 자동으로 작성된다.
또한 인터페이스의 상수는 선언과 동시에 반드시 초기값을 지정해줘야한다.
- public static final 타입 상수명 = 값;
아래의 예제 코드는 인터페이스의 상수 필드 선언의 예를 보여준다.
RemoteControl인터페이스에 MAX_VOLUME, MIN_VOLUME 상수 필드가 선언되어 있다.
package sec01.exam02;
public interface RemoteControl {
//인터페이스는 상수필드와 추상메소드만을 가진다.
//인터페이스 필드는 상수 필드이다.
//인터페이스는 객체 사용 방법을 정의하는 것이므로, 데이터를 저장할 수 있는 인스턴스 또는 정적 필드를 선언할 수 없다.
//인터페이스 필드는 선언과 동시에 반드시 초기화를 해줘야한다.
//인터페이스 필드는 컴파일 과정에서 자동적으로 public static final의 속성을 가진다.
public int MAX_VOLUME = 10;
public int MIN_VOLUME = 0;
}
2) 추상 메소드 선언
인터페이스의 메소드를 호출하면 객체의 메소드가 호출되어 실행된다.
그러므로 인터페이스의 메소드는 실행 블록이 없는 추상 메소드로 선언된다.
인터페이스에 선언된 메소드는 모두 public abatract 특성을 가지며, 생략되더라도 컴파일 과정에서 자동으로 작성된다.
- public abstract 리턴타입 메소드명(매개변수, ...);
아래의 예제 코드는 인터페이스의 추상 메소드 선언 예를 보여준다.
RemoteControl인터페이스에는 turnOn(), turnOff(), setVolume()추상 메소드가 선언되어있다.
모두 실행 블록이 없음을 알 수 있다.
package sec01.exam03;
public interface RemoteControl {
//인터페이스 필드(상수)
public int MAX_VOLUME = 10;
public int MIN_VOLUME = 0;
//인터페이스 메소드는 객체에서 실행되므로, 실행블록이 없는 추상메소드로 선언한다.
//인터페이스에 선언된 추상메소드는 모두 public abstract가 컴파일 시에 자동으로 적용된다.
public void turnOn();
public void turnOff();
public void setVolume(int volume);
}
3. 인터페이스 구현
개발 코드가 인터페이스의 추상 메소드를 호출하면, 객체의 메소드가 호출된다.
객체의 메소드가 호출되기 위해서는 인터페이스의 추상 메소드와 동일한 리턴 타입, 메소드명, 매개 타입을 가진 메소드여야 한다.
이러한 메소드를 가진 객체를 구현 객체라고 하며, 구현 객체를 생성하는 클래스를 구현 클래스라고 한다.
1) 구현 클래스
구현 클래스의 선언은 보통의 클래스와 동일 하지만 인터페이스 타입으로 사용될 수 있음을 알려주기 위해 클래스 선언 부에 implements 인터페이스명 키워드를 추가한다.
그리고 추상 메소드의 구현 메소드를 선언해야한다.
- public class 구현클래스명 implements 인터페이스명 { 실체 메소드 };
아래의 예제 코드는 RemoteControl인터페이스를 상속하는 Television, Audio클래스를 통해 구현 클래스의 예를 보여준다.
Television, Audio클래스는 RemoteControl을 상속하고 있으며 3개의 추상 메소드에 대한 구현 메소드가 선언되어 있다.
package sec01.exam04;
import sec01.exam03.RemoteControl;
public class Audio implements RemoteControl {
//필드
private int volume;
//turnOn() 추상메소드의 실체메소드
public void turnOn() {
System.out.println("Audio를 켭니다.");
}
//turnOff() 추상메소드의 실제메소드
public void turnOff() {
System.out.println("Audio를 끕니다.");
}
//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("현재 Audio 볼륨: " + this.volume);
}
}
package sec01.exam04;
import sec01.exam03.RemoteControl;
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 볼륨: " + this.volume);
}
}
Televison, Audio처럼 구현 클래스가 작성되면, 아래와 같이 일반 클래스처럼 new 연산자를 통해 구현 클래스 타입의 객체를 생성할 수 있다.
그러나 이것은 인터페이스의 기능을 사용한 것이 아니다.
- Television tv = new Television();
인터페이스를 통해 구현 객체를 사용하려면 인터페이스 타입의 변수를 선언하고, 구현 클래스의 생성자를 통해 객체를 대입해야한다.
아래의 예제 코드는 구현 객체 사용의 예를 보여준다.
RemoteControl 타입의 변수 rc를 선언하고, rc변수에 Television, Audio구현 객체를 대입하여 사용할 수 있다.
package sec01.exam04;
import sec01.exam03.RemoteControl;
public class RemoteControlExample {
public static void main(String[] args) {
RemoteControl rc;
rc = new Television();
rc = new Audio();
}
}
2) 다중 인터페이스 구현 클래스
자식 클래스가 하나의 부모 클래스만 상속하는 것과는 달리, 구현 클래스는 여러 개의 인터페이스를 상속할 수 있다.
이러한 구현 클래스는 여러 개의 인터페이스를 구현해야하므로, 상속하고 있는 모든 인터페이스의 추상 메소드에 대한 구현 메소드가 선언되어야한다.
아래의 예제 코드는 Searchable인터페이스, 그리고 앞서 선언한 RemoteControl인터페이스를 상속하는 SmartTelevision 구현 클래스를 통해 다중 인터페이스 구현 클래스의 예를 보여준다.
SmartTelevision구현 클래스는 RemoteControl, Searchable인터페이스를 상속하고 있다.
그리고 두 인터페이스를 구현하기 위해 두 인터페이스의 모든 추상 메소드에 대한 구현 메소드가 선언되어 있다.
그리고 SmartTelevision객체는 RemoteControl, Searchable 타입 변수에 대입 가능하다.
package sec01.exam05;
public interface Searchable {
void search(String url);
}
package sec01.exam05;
import sec01.exam03.RemoteControl;
public class SmartTelevision implements RemoteControl, Searchable {
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);
}
public void search(String url) {
System.out.println(url + "을 검색합니다.");
}
}
package sec01.exam05;
import sec01.exam03.RemoteControl;
public class SmartTelevisionExample {
public static void main(String[] args) {
SmartTelevision tv = new SmartTelevision();
RemoteControl rc = tv;
Searchable searchable = tv;
}
}
4. 인터페이스 사용
인터페이스는 특정 클래스에서 필드, 생성자 또는 메소드의 매개변수 및 로컬변수로 사용될 수 있다.
아래의 예제 코드는 RemoteControl인터페이스가 실제 사용되는 예를 보여준다.
우선 MyClass클래스 내부에 RemoteControl인터페이스 타입의 rc변수가 필드로 선언되어있다. 그리고 rc변수에는 RemoteControl인터페이스의 구현 객체인 Television객체가 대입되어있다.
그리고 MyClass(RemoteControl rc) { ... }와 methodB(RemoteControl rc) { ... }처럼 생성자, 메소드의 매개변수로 RemoteControl인터페이스가 사용되고 있음을 알 수 있다.
또한 methodA()메소드 실행 블록을 보면 RemoteControl rc = new Audio();처럼 RemoteControl인터페이스가 메소드의 로컬변수로 사용되고 있음을 알 수 있다.
이제 MyClass를 사용하는 MyClassExample클래스 내부를 보자.
MyClass 타입의 myClass1, myClass2, myClass3변수가 생성되었다.
그리고 RemoteControl인터페이스는 MyClass클래스의 필드, 매개변수, 로컬변수로 사용되어 다양한 실행결과를 나타낼 것이다.
package sec01.exam06;
import sec01.exam03.RemoteControl;
import sec01.exam04.Audio;
import sec01.exam04.Television;
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);
}
}
package sec01.exam06;
import sec01.exam04.Audio;
import sec01.exam04.Television;
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());
}
}
출처: 혼자 공부하는 자바(신용권)