Claire's Study Note

08-1. 인터페이스

by Hi.Claire
반응형

📓 혼자 공부하는 자바 (신용권, 한빛미디어)

 

08. 인터페이스

08-1. 인터페이스

인터페이스(Interface)

객체의 사용 방법을 정의한 타입

개발 코드와 객체가 서로 통신하는 접점 역할을 한다.

개발 코드가 인터페이스의 메소드를 호출하면 인터페이스는 객체의 메소드를 호출한다.

그렇기 때문에 개발 코드는 객체의 내부 구조를 알 필요가 없고 인터페이스의 메소드만 알고 있으면 된다.

-> 인터페이스와 구현의 분리

 

개발 코드와 객체 사이에 인터페이스를 두는 이유

개발 코드가 직접 객체의 메소드를 호출하지 않고 중간에 인터페이스를 두는 이유는 개발 코드를 수정하지 않고 사용하는 객체를 변경할 수 있도록 하기 위해서다.

인터페이스는 하나의 객체가 아니라 여러 객체들과 사용이 가능하므로 어떤 객체를 사용하느냐에 따라서 실행 내용과 리턴값이 달라질 수 있다.

따라서 개발 코드 측면에서는 코드 변경 없이 실행 내용과 리턴값을 다양화할 수 있다는 장점을 가지게 된다.

 

인터페이스의 메소드는 추상 메소드로 메소드 호출 방법만 기술된다. 각각의 객체에서 메소드가 재정의된다.

 

08-1-1. 인터페이스 선언

인터페이스 선언부에 interface 키워드를 사용한다.

[public] interface 인터페이스이름 { ... }

 

인터페이스는 상수 필드와 추상 메소드만을 구성 멤버로 가진다.

인터페이스는 객체를 생성할 수 없기 때문에 생성자를 가질 수 없다.

 

상수 필드 선언

인터페이스는 객체 사용 방법을 정의한 것이므로 실행 시 데이터를 저장할 수 있는 인스턴스 필드나 정적 필드를 선언할 수 없다.

대신 상수 필드(constant field)는 선언이 가능하다.

단, 상수는 인터페이스에 고정된 값으로 실행 시에 데이터를 바꿀 수 없다.

인터페이스에 선언된 필드는 모두 public static final의 특성을 갖는데, public static final을 생략하더라도 컴파일 과정에서 자동으로 붙게 된다.

[public static final] 타입 상수이름 = 값;

 

인터페이스 상수는 반드시 선언과 동시에 초기값을 지정해야 한다.

 

추상 메소드 선언

인터페이스를 통해 호출된 메소드는 최종적으로 객체에서 실행되기 때문에 인터페이스의 메소드는 실행 블록이 필요 없는 추상 메소드로 선언한다.

인터페이스에 선언된 추상 메소드는 모두 public abstract의 특성을 갖기 때문에 public abstract 키워드를 생략해도 컴파일 과정에서 자동으로 붙게 된다.

[public abstract] 리턴타입 메소드이름(매개변수, ...);

 

예시1. 인터페이스 선언

public interface RemoteControl {

    // 상수
    public int MAX_VOLUME = 10;
    public int MIN_VOLUME = 0;
    
    // 추상 메소드
    public void turnOn();
    public void turnOff();
    public void setVolume(int volume);
}

 

08-1-2. 인터페이스 구현(Implement)

개발 코드가 인터페이스 메소드를 호출하면 인터페이스는 객체의 메소드를 호출한다고 했다.

이때 호출되는 객체는 인터페이스에 정의된 추상 메소드를 재정의해서 실행 내용을 가지는 실체 메소드를 가지고 있어야 한다.

이때 주의할 점은 인터페이스의 모든 추상 메소드는 기본적으로 public 접근 제한을 갖기 때문에 이보다 더 낮은 접근 제한으로 실체 메소드를 작성할 수 없다는 것이다.

이러한 객체를 인터페이스의 구현 객체라고 하고, 구현 객체를 생성하는 클래스를 구현 클래스라고 한다.

 

구현 클래스

클래스 선언부에 implements 키워드를 추가하고 인터페이스 이름을 명시한다.

그리고 인터페이스에 선언된 추상 메소드의 실체 메소드를 선언해야 한다.

public class 구현클래스이름 implements 인터페이스이름 { ... }

 

예시1. 인터페이스의 구현 클래스 - Television

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 < RomoteControl.MIN_VOLUME) {
            this.volume = RemoteControl.MIN_VOLUME;
        } else {
            this.volume = volume;
        }

        System.out.println("현재 TV 볼륨 : " + this.volume);
    }
}

 

예시2. 인터페이스의 구현 클래스 - Audio

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 < RomoteControl.MIN_VOLUME) {
            this.volume = RemoteControl.MIN_VOLUME;
        } else {
            this.volume = volume;
        }

        System.out.println("현재 Audio 볼륨 : " + this.volume);
    }
}

구현 클래스가 작성되면 new 연산자로 객체를 생성할 수 있다.

인터페이스로 구현 객체를 사용하려면 인터페이스 변수를 선언하고 구현 객체를 대입해야 한다.

인터페이스 변수는 참조 타입이기 때문에 구현 객체가 대입될 경우 구현 객체의 번지를 저장한다.

인터페이스 변수 = new 구현객체();

 

다중 인터페이스 구현 객체

객체는 다수의 인터페이스를 구현하여 다수의 인터페이스 타입으로 사용할 수 있다.

 

public class 구현클래스이름 implements 인터페이스A, 인터페이스B { ... }

 

다중 인터페이스를 구현할 경우, 구현 클래스는 모든 인터페이스의 추상 메소드에 대해 실체 메소드를 작성해야 한다.

 

예시3. 인터페이스

public interface Searchable {

    void search(String url);
}

 

예시4. 다중 인터페이스 구현 클래스

public class SmartTelevision implements RemoteControl, Searchable {

    // 필드
    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 < RomoteControl.MIN_VOLUME) {
            this.volume = RemoteControl.MIN_VOLUME;
        } else {
            this.volume = volume;
        }

        System.out.println("현재 TV 볼륨 : " + this.volume);
    }
    
    // search() 추상 메소드의 실체 메소드
    public void search(String url) {
        System.out.println(url + "을 검색합니다.");
    }
}

 

08-1-3. 인터페이스 사용

클래스를 선언할 때 인터페이스는 클래스의 필드, 생성자 또는 메소드의 매개 변수, 생성자 또는 메소드의 로컬 변수로 선언될 수 있다.

 

다시 한 번 정리하면, 인터페이스는 개발 코드와 구현 객체 사이에서 접점 역할을 담당한다.

개발 코드는 인터페이스에 선언된 추상 메소드를 호출하고, 인터페이스는 구현 객체의 재정의 메소드를 호출한다.

 

예시1. 인터페이스 사용

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

 

예시2. 인터페이스 사용

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

 

반응형

'☕️ Java > 혼자 공부하는 자바' 카테고리의 다른 글

08-2. 타입 변환과 다형성  (0) 2023.09.25
07-3. 추상 클래스  (0) 2023.09.24
07-2. 타입 변환과 다형성  (1) 2023.09.23
07-1. 상속  (0) 2023.09.18
06-6. 패키지와 접근 제한자  (0) 2023.09.17

블로그의 정보

Claire's Study Note

Hi.Claire

활동하기