본문 바로가기

개발(합니다)/Java&Spring

[java-기초-08] 인터페이스

반응형

인터페이스란

  • 객체의 사용방법을 정의한 타입으로 객체의 교환성을 높여주며 개발 코드와 객체가 서로 통신하는 접점 역할을 한다.
  • 개발 코드를 수정하지 않고 사용하는 객체를 변경할 수 있도록 해준다.
  • [public] interface 인터페이스명 { }
  • 상수와 메서드만 구성 멤버로 가지마 생성자를 가질 수 없다.
  • 인터페이스는 다중 구현이 가능하다.

인터페이스의 역할

interface 인터페이스명 {
    // 상수
    타입 상수명 = 값;
    // 추상 메서드
    타입 메서드명(매개변수,..);
    // 디폴트 메서드
    default 타입 메서드명(매개변수, ...) { ... }
    // 정적 메서드
    static 타입 메서드명(매개변수, ...) { ... }
} 

인터페이스 내부

    public interface RemoteControl {
        // 상수
        public int MAX_VOLUME = 10; // 상수 필드
        public int MIN_VOLUME = 0; // 상수 필드

        // 추상 메서드
        public void turnOn();
        public void turnOff();
        public 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 구현 클래스명 implements 인터페이스명 {
        // 인터페이스에 선언된 추상 메서드의 실체 메서드 선언
    }

주의 사항

  • 인터페이스의 모든 메서드는 기본적으로 public 접근 제한을 갖기 때문에 public보다 더 낮은 접근 제한으로 작성할 수 없다.
  • 만약 인터페이스에 선언된 추상 메서드에 대응하는 실체 메서드를 구현 클래스가 작성하지 않으면 구현 클래스는 자동적으로 추상 클래스가 된다.

익명 구현 객체

  • 일회성의 구현 객체를 만들기 위해 소스파일을 만들고 클래스를 선언하는 것은 비효율적이므로 구현 객체를 만들지 않고 객체를 사용할 수 있다.
  • UI 프로그래밍에서 이벤트성을 처리하기 위해, 임시 작업으로 스레드를 만들기 위해 활용한다.
  • 하나의 실행문의 끝에는 세미콜론(;)을 반드시 붙여야 한다.
  • 중괄호 {}에는 인터페이스에 선언된 모든 추상 메서드들의 실체 메서드를 작성해야 한다.

실습

public class Test3 {
    Television t = new Television();
    Audio a = new Audio();

    interface RemoteControl {
        // 상수
        public int MAX_VOLUME = 10; // 상수 필드
        public int MIN_VOLUME = 0; // 상수 필드

        // 추상 메서드
        public void turnOn();

        public void turnOff();

        public void setVolume(int volume);

        // 디폴트 메서드
        default void setMute(boolean mute) {
            if (mute) {
                System.out.println("무음 처리합니다.");
            } else {
                System.out.println("무음 해제합니다.");
            }
        }

        // 정적 메서드
        static void changeBattery() {
            System.out.println("건전지를 교환합니다.");
        }
    }

    class Television implements RemoteControl {
        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 볼륨 : " + volume);
        }
    }

    class Audio implements RemoteControl {
        private int volume;
        private boolean mute;

        public void turnOn() {
            System.out.println("Audio를 켭니다.");
        }

        public void turnOff() {
            System.out.println("Audio를 끕니다.");
        }

        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);
        }

        @Override
        public void setMute(boolean mute) { // 디폴트 메서드 사용
            this.mute = mute;
            if (mute) {
                System.out.println("Audio 무음 처리합니다.");
            } else {
                System.out.println("Audio 무음 해제합니다.");

            }
        }
    }

    class MyClass {

        RemoteControl rc = new Television(); // 클래스의 필드로 선언 가능하다.

        MyClass(RemoteControl rc) { // 생성자의 매개변수로 선언 가능하다.
            this.rc = rc;
        }

        void methodA() {
            RemoteControl rc = new Audio(); // 메서드의 로컬 변수로 선언 가능하다.
        }
    }

    public static void main(String[] args) {
        RemoteControl rc = null;
        Test3 t = new Test3();
        rc = t.t;
        rc.turnOn();
        rc.turnOff();
        rc = t.a;
        rc.turnOn();
        rc.turnOff();

    }
}

타입 변환과 다형성

  • 하나의 타입에 대입되는 객체에 따라서 실행 결과가 다양한 형태로 나오는 성질을 말한다.
  • A 클래스의 성능이 나오지 않아 B로 변경해야는 경우에 인터페이스를 기준으로 A의 선언부가 동일하다면 쉽게 변경 가능하다.
interface I {  
void method1();  
void method2();  
}

public static void main(String args[]){

// I i = new A(); 
I i = new B();

i.method1();
i.method2();

}

추상 클래스와 같음

자동 타입 변환(Promotion)

  • 인터페이스 변수 = 구현객체 // 자동 타입 변환

B b = new B();
C c = new C();
D d = new D();
E e = new E();

A a1 = b; // 가능
A a2 = c; // 가능
A a3 = d; // 가능
A a4 = e; // 가능

필드의 다형성

public interface Tire {
    public void roll();
}

매개 변수의 다형성

public interface Vehicle {
    public void run();
    }

강제 타입 변환

  • 구현클래스 변수 = (구현클래스) 인터페이스 변수; // 강제 타입 변환

객체 타입 확인

  • instanceof로 타입을 확인한다.

인터페이스 상속

  • public interface 하위인터페이스 extends 상위인터페이스1, 상위인터페이스2 { ... }

디폴트 메서드와 인터페이스의 확장 및 디폴트 메서드의 필요성

  • 기존 인터페이스를 확장해 새로운 기능을 추가하기 위해서 허용되었다.
  • 디폴트 메서드는 추상 메서드가 아니기 때문에 구현 클래스에서 실체 메서드를 작성할 필요가 없다.

디폴트 메서드가 있는 인터페이스 상속

  • 사용방법
    • 디폴트 메서드를 단순히 상속만 받는다.
    • 디폴트 메서드를 재정의해서 실행 내용을 변경한다.
    • 디폴트 메서드를 추상 메서드로 재선언한다.
반응형