- 개발 코드와 객체가 서로 통싞하는 접점
- 개발 코드는 읶터페이스의 메소드만 알고 있으면 OK
- 인터페이스의 역할
• 개발 코드가 객체에 종속되지 않게 -> 객체 교체할 수 있도록 하는 역할
• 개발 코드 변경 없이 리턴값 또는 실행 내용이 다양해 질 수 있음 (다형성)
/*
* access modifier가 기본적으로 public이 원칙
*/
public interface RemoteControl {
// public int static final int MAX_VOLUME = 10;
int MAX_VOLUME = 10; //상수
public int MIN_VOLUME = 0; //상수
public abstract void turnOff();
// public abstact void turn on();
void turnOn();
public void setVolume(int volume);
}
/*
* Audio class는 RemoteControl interface의 자식 클래스라고 생각하면 됨
* RemoteControl interface는 audio class의 부모 class라고 생각하면 됨
*/
public class Audio implements RemoteControl {
private int volume;
@Override
public void turnOff() {
System.out.println("Audio를 끕니다");
}
@Override
public void turnOn() {
System.out.println("Audio를 켭니다");
}
@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("현재 Audio Volume : " + this.volume);
}
}
/*
* Interface 정의
* 1. 상수와 abstract method만 사용하는 것을 말함(원칙)
* -2016년 Java 1.8V 부터 default method,static method를 추가 했음
* 2. 문법
* -filed 선언할때 public static final 키워드를 사용하지 않아도 Java에서 자동으로 변환(상수)
* -method 선언할 때 public abstract 키워드를 사용하지 않아도 Java에서 자동으로 변환
* 3. Interface 사용의 기본 polymophism 방식으로 사용하는 것이 기본
* -사용방법 : 인터프에스 이름(부모) 변수이름 = 인터페이스구현 클래스(자식)인스턴스
* "변수이름.추상메소드구현한메소드" 방식으로 사용
* 4. 부모class 역할을 하는 Interface는 기본적으로 힙메모리에 생성이 되지 않음
*/
public class Main {
public static void main(String[] args) {
// RemoteControl interface이름이 data type으로 간주
RemoteControl rc;
// rc = new Television();
rc = new Audio(); //promotion
rc.turnOn(); //polymorphism
rc.setVolume(7);
rc.turnOff();
}
}
- 명시적인 구현 클래스 작성 생략하고 바로 구현 객체를 얻는 방법
• 이름 없는 구현 클래스 선언과 동시에 객체 생성
• 인터페이스의 추상 메소드들을 모두 재정의하는 실체 메소드가 있어야
• 추가적으로 필드와 메소드 선언 가능하나 익명 객체 안에서만 사용
• 인터페이스 변수로 접근 불가
public interface RemoteControl {
int MAX_VOLUME = 10;
public int MIN_VOLUME = 0;
public abstract void turnOff();
void turnOn();
public void setVolume(int volume);
}
/*
* 익명객체 (Anonymous Instance)
* 1. Interface를 import한 인스턴스를 의미
* 2. 자식 class를 공식적으로 만들지 않고 1회성으로 자식클래스를 만들기 원할 때 사용
* 3. Android mobile app programing 에서 많이 사용
*/
public class Main {
public static void main(String[] args) {
// 익명객체
RemoteControl rc = new RemoteControl() {
int volume;
@Override
public void turnOn() {
System.out.println("Anonymous(익명)객체 - 전원 켭니다");
}
@Override
public void turnOff() {
System.out.println("Anonymous(익명)객체 - 전원 끕니다");
}
@Override
public void setVolume(int volume) {
this.volume = volume;
System.out.println("Anonymous(익명)객체 - volume : " + volume);
}
};
rc.turnOn(); //polymorphism
rc.setVolume(7);
rc.turnOff();
}
}
- default method 선언가능
- method 이름 앞에 명시적으로 'default' 라는 키워드를 넣음
-class 에서는 default method 선언할 때 'default'키워드 넣지 않음- static method 선언 가능
-public static 으로 인식- default method와 static method를 java 1.8부터 Interface 사양에 추가한 목적
-Interface의 확장성을 목적으로 함
public interface RemoteControl {
int MAX_VOLUME = 10; //상수
public int MIN_VOLUME = 0; //상수
void turnOff();
void turnOn();
void setVolume(int volume);
default void setMute(boolean mute) {
if(mute) {
System.out.println("무음 처리합니다");
}else {
System.out.println("무음 해제합니다");
}
}
static void changeBattery() {
System.out.println("건전지를 교체합니다");
}
}
public class RemoteControlEx {
public static void main(String[] args) {
RemoteControl rc;
rc = new Television();
rc.turnOn(); //polymorphism
rc.setMute(true);
rc.setVolume(7);
rc.setMute(false);
rc.turnOff();
System.out.println();
RemoteControl.changeBattery();
System.out.println();
rc = new Audio(); //promotion
rc.turnOn(); //polymorphism
rc.setMute(true);
rc.setVolume(7);
rc.setMute(false);
rc.turnOff();
}
}
하나의 타입에 여러 가지 객체 대입해 다양한 실행 결과를 얻는 것
- 다형성을 구현하는 기술
• 상속 또는 읶터페이스의 자동 타입 변홖(Promotion)
• 오버라이딩(Overriding)- 다형성의 효과
• 다양한 실행 결과를 얻을 수 있음
• 객체를 부품화시킬 수 있어 유지보수 용이 (메소드의 매개변수로 사용)
public interface Vehicle {
void run();
}
public class Bus implements Vehicle {
@Override
public void run() {
System.out.println("버스가 달립니다");
}
}
public class Taxi implements Vehicle {
@Override
public void run() {
System.out.println("택시가 달립니다");
}
}
public class Driver {
// method parameter의 data type으로 Interface를 사용할 수 있음
// promotion 발생(자식 class에서 부모인 Interface type으로 변환)
public void driver(Vehicle vehicle) {
vehicle.run(); //polymorphism
}
}
public class Main {
public static void main(String[] args) {
Driver driver = new Driver();
Bus bus = new Bus();
Taxi taxi = new Taxi();
driver.driver(bus);
driver.driver(taxi);
}
}
- Interface 상속(inheritance)
- 여러개의 부모 interface를 상속 가능
- 부모 interface를 상속할 때는 class 처럼 extends 키워드 사용
public interface InterfaceA {
void methodA();
}
public interface InterfaceB {
void methodB();
}
public interface InterfaceC extends InterfaceA, InterfaceB {
void methodC();
}
public class ImplementationC implements InterfaceC {
@Override
public void methodA() {
System.out.println("methodA 실행");
}
@Override
public void methodB() {
System.out.println("methodB 실행");
}
@Override
public void methodC() {
System.out.println("methodC 실행");
}
}
public class Main {
public static void main(String[] args) {
ImplementationC impl = new ImplementationC();
InterfaceA ia = impl;
ia.methodA();
// ia.methodB();
// ia.methodC();
InterfaceB ib = impl;
// ib.methodA();
ib.methodB();
// ib.methodC();
InterfaceC ic = impl;
ic.methodA();
ic.methodB();
ic.methodC();
}
}
- 디폴트 메소드가 있는 읶터페이스 상속
- 부모 인터페이스의 디폴트 메소드를 자식 읶터페이스에서 홗용 방법
• 디폴트 메소드를 단순히 상속만 받음
• 디폴트 메소드를 재정의(Override)해서 실행 내용을 변경
• 디폴트 메소드를 추상 메소드로 재선언
public interface ParaentInterface {
void method1();
default void method2() {
System.out.println("ParaentInterface - default method2 실행");
}
}
public interface ChildInterface extends ParaentInterface {
void method3();
@Override
void method2();
}
- 부모 Interface에서 선언된 default method를 자식 Interface에서 사용하는 방법
1. 부모 Interface에서 선언된 default method를 단순 사용
- 부모 Interface에서 선언된 default method를 자식 Interface에서 override하여 사용
- 부모 Interface에서 선언된 default method를 자식 Interface에서 abstract method로 사용
package p07.default_method_inheritance2;
public class ChildInterfaceEx {
public static void main(String[] args) {
ChildInterface ci = new ChildInterface() {
@Override
public void method1() {
System.out.println("익명 method1 실행");
}
@Override
public void method3() {
System.out.println("익명 method3 실행");
}
@Override
public void method2() {
System.out.println("익명 method2 실행");
}
};
ci.method1();
ci.method2();
ci.method3();
}
}