인터페이스

hovi·2023년 5월 30일
0

JAVA

목록 보기
12/36

인터페이스란?

자식 클래스가 여러 부모 클래스를 상속받을 수 있다면, 다양한 동작을 수행할 수 있다는 장점을 가지게 될 것입니다.

하지만 클래스를 이용하여 다중 상속을 할 경우 메소드 출처의 모호성 등 여러 가지 문제가 발생할 수 있어 자바에서는 클래스를 통한 다중 상속은 지원하지 않습니다.

하지만 다중 상속의 이점을 버릴 수는 없기에 자바에서는 인터페이스라는 것을 통해 다중 상속을 지원하고 있습니다.

인터페이스(interface)란 다른 클래스를 작성할 때 기본이 되는 틀을 제공하면서, 다른 클래스 사이의 중간 매개 역할까지 담당하는 일종의 추상 클래스를 의미합니다.

자바에서 추상 클래스는 추상 메소드뿐만 아니라 생성자, 필드, 일반 메소드도 포함할 수 있습니다.

하지만 인터페이스(interface)는 오로지 추상 메소드와 상수만을 포함할 수 있습니다.

  • 상수 : 모든 필드는 자동으로 상수(final static)으로 변환 됩니다.
  • 메소드 : 모든 메소드는 추상 메소드로 변경되며(public abstract 자동으로 추가) 상속 받은 클래스에서 구현 해야 함
  • 디폴트 메소드 : 구현부를 가지고 있으며, 상속 받은 클래스에서 재정의 하여 사용 가능 합니다.
  • 정적 메소드 : 객체와 상관없이 인터페이스 타입으로 사용 할수 있습니다.

인터페이스의 선언

인터페이스를 선언할 때에는 접근 제어자와 함께 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("네트워크 선택이 잘 못 되었습니다.");
        }
    }
}

예제를 매개변수의 다형성을 이용 수정

  • CocoaTok class 별도 생성
  • Send와 Rcv는 인터페이스 상속으로 구현해서 CocoTok의 전송 기능으로 연결
  • 전송시 자동으로 네트워크를 찾아주면 좋으나 우선은 조건문으로선택해서 연결
  • 매개변수 다형성을 이용해서 해결
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);
    }
}

리모컨 예제 (인터페이스)

RemoteControl.java

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("건전지를 교환 합니다.");
    }
}

Audio.java

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 + " 입니다.");
    }
}

Main.java

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();
}
profile
풀스택 예비 개발자

0개의 댓글

관련 채용 정보