자식 클래스가 여러 부모 클래스를 상속받을 수 있다면, 다양한 동작을 수행할 수 있다는 장점을 가지게 될 것입니다.
하지만 클래스를 이용하여 다중 상속을 할 경우 메소드 출처의 모호성 등 여러 가지 문제가 발생할 수 있어 자바에서는 클래스를 통한 다중 상속은 지원하지 않습니다.
하지만 다중 상속의 이점을 버릴 수는 없기에 자바에서는 인터페이스라는 것을 통해 다중 상속을 지원하고 있습니다.
인터페이스(interface)란 다른 클래스를 작성할 때 기본이 되는 틀을 제공하면서, 다른 클래스 사이의 중간 매개 역할까지 담당하는 일종의 추상 클래스를 의미합니다.
자바에서 추상 클래스는 추상 메소드뿐만 아니라 생성자, 필드, 일반 메소드도 포함할 수 있습니다.
하지만 인터페이스(interface)는 오로지 추상 메소드와 상수만을 포함할 수 있습니다.
인터페이스를 선언할 때에는 접근 제어자와 함께 interface 키워드를 사용하면 됩니다.
접근제어자 interface 인터페이스이름 {
public static final 타입 상수 이름 = 값;
...
public abstract 메소드이름(매겨변수 목록)'
}
클래스와는 달리 인터페이스의 모든 필드는 public static final이어야 하며, 모든 메소드는 public abstract이어야 합니다. 이 부분은 모든 인터페이스에 공통으로 적용되는 부분이므로 부분이므로 이 제어자는 생략할 수 있습니다. 생략하면 제어자는 컴파일 시 컴파일러가 자동으로 추가해 줍니다.
인터페이스는 추상 클래스와 마찬가지로 자신이 직접 인스턴스를 생성 할 수 없습니다.
따라서 인터페이스가 포함하고 있는 추상 메소드를 구현해 줄 클래스를 작성해야만 합니다.
class 클래스이름 implements 인터페이스이름 {…}
package 인터페이스;
import java.util.Scanner;
interface NetworkAdapter {
public abstract void connect();
}
class LAN implements NetworkAdapter {
String company;
LAN(String company) {
this.company = company;
}
@Override
public void connect() {
System.out.println(company + " LAN에 연결 되었습니다.");
}
}
class WiFi implements NetworkAdapter {
String company;
WiFi(String company) {
this.company = company;
}
@Override
public void connect() {
System.out.println(company + " WiFi에 연결 되었습니다.");
}
}
class LTE implements NetworkAdapter {
String company;
LTE(String company) {
this.company = company;
}
@Override
public void connect() {
System.out.println(company + " LTE에 연결 되었습니다.");
}
}
public class Main {
public static void main(String[] args) {
NetworkAdapter adapter;
Scanner sc = new Scanner(System.in);
System.out.print("연결할 네트워크를 선택 하세요[1]LAN, [2]WiFi, [3]LTE : ");
int num = sc.nextInt();
switch(num) {
case 1 :
adapter = new LAN("KT Magapass");
adapter.connect();
break;
case 2 :
adapter = new WiFi("SK Telecom");
adapter.connect();
break;
case 3 :
adapter = new LTE("LG U+");
adapter.connect();
break;
default :
System.out.println("네트워크 선택이 잘 못 되었습니다.");
}
}
}
package 인터페이스;
import java.util.Scanner;
interface NetworkAdapter {
public abstract void connect();
default void description() {
System.out.println("자바8에서 추가된 새로운 메소드 입니다.");
}
}
class Chat {
Chat() {
}
public void sendMsg() {
System.out.println("메시지를 보냅니다.");
}
public void rcvMsg() {
System.out.println("메시지를 받습니다.");
}
}
class LAN extends Chat implements NetworkAdapter {
String company;
String name;
LAN(String company, String name) {
this.company = company;
this.name = name;
}
//default void description() {
// System.out.println("자바8에서 추가된 새로운 메소드 입니다.");
//}
@Override
public void connect() {
System.out.println(company + " LAN에 연결 되었습니다.");
}
public void sendMsg() {
System.out.println(name + "에게 메시지를 보냅니다.");
}
public void rcvMsg() {
System.out.println(name + "으로 부터 메시지를 받습니다.");
}
}
class WiFi implements NetworkAdapter {
String company;
String name;
WiFi(String company, String name) {
this.company = company;
this.name = name;
}
@Override
public void connect() {
System.out.println(company + " WiFi에 연결 되었습니다.");
}
public void sendMsg() {
System.out.println(name + "에게 메시지를 보냅니다.");
}
public void rcvMsg() {
System.out.println(name + "으로 부터 메시지를 받습니다.");
}
}
class LTE implements NetworkAdapter {
String company;
LTE(String company) {
this.company = company;
}
@Override
public void connect() {
System.out.println(company + " LTE에 연결 되었습니다.");
}
}
public class Main {
public static void main(String[] args) {
NetworkAdapter adapter;
Scanner sc = new Scanner(System.in);
System.out.print("연결할 네트워크를 선택 하세요[1]LAN, [2]WiFi, [3]LTE : ");
int num = sc.nextInt();
switch(num) {
case 1 :
adapter = new LAN("KT Magapass", "고유림");
adapter.connect();
((LAN) adapter).sendMsg();
((LAN) adapter).rcvMsg();
break;
case 2 :
adapter = new WiFi("SK Telecom", "나희도");
adapter.connect();
((WiFi) adapter).sendMsg();
((WiFi) adapter).rcvMsg();
break;
case 3 :
adapter = new LTE("LG U+");
adapter.connect();
break;
default :
System.out.println("네트워크 선택이 잘 못 되었습니다.");
}
}
}
public class CocoaMain {
public static void main(String[] args) {
CocoaTok cocoaTok = new CocoaTok("2NE1");
cocoaTok.writeMsg("오늘 춥죠??");
NetAdapter adapter;
Scanner sc = new Scanner(System.in);
System.out.print("네트워크 [1]WiFi [2]5G");
int sel = sc.nextInt();
if(sel == 1) adapter = new WiFi();
else adapter = new FiveG();
cocoaTok.send(adapter);
}
}
public class CocoaTok {
private String to; // 상대방이름
private String msg; // 전달할 메시지
public CocoaTok(String name) {
to = name;
}
public void writeMsg(String msg) {
this.msg = to + " : " + msg;
}
public void send(NetAdapter na) {
na.send(msg);
}
}
public interface NetAdapter {
void connect();
void send(String msg);
}
class WiFi implements NetAdapter {
@Override
public void connect() {}
@Override
public void send(String msg) {
System.out.println("WiFi >> " + msg);
}
}
class FiveG implements NetAdapter {
@Override
public void connect() {}
@Override
public void send(String msg) {
System.out.println("5G >> " + msg);
}
}
package 인터페이스디폴트메소드;
public interface RemoteControl {
int MAX_VOLUME = 100; // 상수로 정의 하지 않았지만 상수 이다.
int MIN_VOLUME = 0;
// 추상 메소드 : abstract 를 생략 했지만 수창 메소드 이다.
void turnOn();
void turnOff();
void setVolume(int volume);
// 정적 메소드
// 인터페이스의 정적 메소드는 인터페이스로 호출 가능 하다.
static void changeBattery() {
System.out.println("건전지를 교환 합니다.");
}
}
public class Audio implements RemoteControl{
private int volume;
@Override
public void turnOn() {
System.out.println("Audio 를 켭니다.");
}
@Override
public void turnOff() {
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 볼륨 : " + this.volume);
}
void getInfo() {
System.out.println("오디오 입니다.");
System.out.println("현재 볼륨은 " + volume + " 입니다.");
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("제품을 선택 하세요(1.TV/2.AUDIO) : ");
int selType = sc.nextInt();
RemoteControl rc;
if(selType == 1) {
rc = new Television();
rc.turnOn();
rc.setVolume(20);
((Television) rc).getInfo();
} else {
rc = new Audio();
rc.turnOn();
rc.setVolume(20);
((Audio) rc).getInfo();
}
}
public static void main(String[] args) {
RemoteControl rc = new RemoteControl() {
@Override
public void turnOn() {
System.out.println("Test");
}
@Override
public void turnOff() {
}
@Override
public void setVolume(int volume) {
}
};
rc.turnOn();
}