본문 바로가기
언어/java

[Java] 8. 인터페이스 (2) - 4~7

by 젼젼39 2025. 5. 25.

8.4 추상 메소드

    - 인터페이스는 구현 클래스가 재정의해야 하는 public 추상 메소드를 멤버로 가질 수 있음

    * 추상 메소드 : 리턴 타입, 메소드명, 매개변수만 기술/ 중괄호 {}를 붙이지 않는 메소드
                         - public abstract를 생략하더라도 컴파일 과정에서 자동으로 붙게 됨
                         => 객체 A가 인터페이스를 통해 어떻게 메소드를 호출할 수 있는지 방법을 알려주는 역할을 함
                              (인터페이스 구현 객체 B는 추상 메소드의 실행부를 갖는, 재정의된 메소드가 있어야 함)

객체 A -- 메소드 호출 --> 인터페이스 -- 메소드 호출 --> 객체 B
<-- 리턴값 -- <-- 리턴값
    추상 메소드
(메소드 선언부)
(호출 방법만 기술)
  재정의된 메소드
(실제 실행 코드를
가지고 있는 메소드)
[public abstract] 리턴타입 메소드명(매개변수, ...);
public interface RemoteControl {
    //상수 필드
    int MAX_VOLUME = 10;
    int MIN_VOLUMT = 0;
    
    //추상 메소드
    // 메소드 선언부만 작성!!
    void turnOn();
    void turnOff();
    void setVolume(int volume);
}

    - 구현 클래스들은 인터페이스에 선언된 모든 추상 메소드재정의해 실행 코드를 가져야 함

public class Television implements RemoteControl {
    //필드
    private int volume;
    
    //turnOn() 추상 메소드 오버라이딩
    @Override
    public void turnOn() {
        System.out.println("TV를 켭니다.");
    }
    
    //turnOff() 추상 메소드 오버라이딩
    @Override
    public void turnOff() {
        System.out.println("TV를 끕니다.");
    }

    //setVolume() 추상 메소드 오버라이딩
    @Override
    public void setVolume(int volume) {
        //인터페이스 상수 필드를 이용해 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 볼륨 : " + this.volume);
    }
}
public class Audio implements RemoteControl {
    //필드
    private int volume;
    
    //turnOn() 추상 메소드 오버라이딩
    @Override
    public void turnOn() {
        System.out.println("Audio를 켭니다.");
    }
    
    //turnOff() 추상 메소드 오버라이딩
    @Override
    public void turnOff() {
        System.out.println("Audio를 끕니다.");
    }

    //setVolume() 추상 메소드 오버라이딩
    @Override
    public void setVolume(int volume) {
        //인터페이스 상수 필드를 이용해 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);
    }
}

    * 구현 클래스에서 추상 메소드를 재정의할 때 주의할 점
        : 인터페이스의 추상 메소드는 기본적으로 public 접근 제한을 가짐 --> public보다 더 낮은 접근 제한으로 재정의 불가
        => 재정의되는 메소드에는 모두 public이 추가되어 있음

public class RemoteControlExample {
    public static void main(String[] args) {
        //인터페이스 변수 선언
        RemoteControl rc;
        
        //Television 객체를 생성, 인터페이스 변수에 대입
        //  인터페이스로 Television 객체 사용
        rc = new Television();
        rc.turnOn();
        rc.setVolume(5);
        rc.turnOff();
    }
}

 

8.5 디폴트 메소드

    - 인터페이스에는 완전한 실행 코드를 가진 디폴트 메소드를 선언할 수 있음

    * 디폴트 메소드 : 실행부 (중괄호 { })가 있음
        - 실행부에는 상수 필드를 읽거나 추상 메소드를 호출하는 코드를 작성할 수 있음
        - 디폴트 메소드는 구현 객체가 필요한 메소드
            -> 구현 객체를 인터페이스 변수에 대입한 뒤에 해당 메소드를 호출해야 함 ( . 연산자 사용)

    - 선언 방법 : 클래스 메소드와 동일, but default 키워드가 리턴 타입 앞에 붙음

[public] default 리턴타입 메소드명(매개변수, ...) {...}
public interface RemoteControl {
    //상수 필드
    int MAX_VOLUME = 10;
    int MIN_VOLUMT = 0;
    
    //추상 메소드
    // 메소드 선언부만 작성!!
    void turnOn();
    void turnOff();
    void setVolume(int volume);
    
    //디폴트 인스턴스 메소드
    default void setMute(boolean mute) {
        if(mute) {
            System.out.println("무음 처리됩니다.");
            //추상 메소드 호출하면서 상수 필드를 사용함.
            setVolume(MIN_VOLUME);
        } else {
            System.out.println("무음 해제합니다.");
        }
    }
}
public class RemoteControlExample {
    public static void main(String[] args) {
        //인터페이스 변수 선언
        RemoteControl rc;
        
        //Television 객체를 생성, 구현 객체를 인터페이스 변수에 대입
        //  인터페이스로 Television 객체 사용
        rc = new Television();
        rc.turnOn();
        rc.setVolume(5);
        
        //디폴트 메소드 호출
        rc.setMute(true);
        rc.setMute(false);
    }
}

    - 구현 클래스는 디폴트 메소드를 재정의해 자신에게 맞게 수정 가능!
        * public 접근 제한자를 반드시 붙여야 함
        * default 키워드를 생략해야 함

public class Audio implements RemoteControl {
    //필드
    private int volume;
    
    //turnOn() 추상 메소드 오버라이딩
    @Override
    public void turnOn() {
        System.out.println("Audio를 켭니다.");
    }
    
    //turnOff() 추상 메소드 오버라이딩
    @Override
    public void turnOff() {
        System.out.println("Audio를 끕니다.");
    }

    //setVolume() 추상 메소드 오버라이딩
    @Override
    public void setVolume(int volume) {
        //인터페이스 상수 필드를 이용해 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);
    }
    
    // 추가 필드 선언
    private int memoryVolume;
    
    //디폴트 메소드 재정의
    @Override
    public void setMute(boolean mute) {
        if(mute) {
            //무음처리하기 전, 저장해두는 부분!
            this.memoryVolume = this.volume;
            System.out.println("무음 처리합니다.");
            setVolume(RemoteControl.MIN_VOLUME);
        } else {
            System.out.println("무음 해제합니다.");
            //mute가 false인 경우, 원래 볼륨으로 복원...
            // 무음처리하기 전에 저장해둔 것을 사용해 복원!
            setVolume(this.memoryVolume);
        }
    }
}

 

8.6 정적 메소드

    - 인터페이스에는 정적 메소드도 선언 가능
        (추상 메소드, 디폴트 메소드는 구현 객체가 필요)
        (정적 메소드는 구현 객체가 없어도 인터페이스만으로 접근해 호출 가능!)

    - public을 생략해도, 자동으로 컴파일 과정에서 붙는다

    - 정적 메소드의 실행부 (중괄호 { }) 작성 시 주의할 점
        * 상수 필드를 제외한 추상 메소드, 디폴트 메소드, private 메소드 등을 호출할 수 없다는 것
          (구현 객체가 필요한 인스턴스 메소드들이라서!)

[public | private] static 리턴타입 메소드명(매개변수, ...) {...}
public interface RemoteControl {
    //상수 필드
    int MAX_VOLUME = 10;
    int MIN_VOLUMT = 0;
    
    //추상 메소드
    // 메소드 선언부만 작성!!
    void turnOn();
    void turnOff();
    void setVolume(int volume);
    
    //디폴트 인스턴스 메소드
    default void setMute(boolean mute) {
        if(mute) {
            System.out.println("무음 처리됩니다.");
            //추상 메소드 호출하면서 상수 필드를 사용함.
            setVolume(MIN_VOLUME);
        } else {
            System.out.println("무음 해제합니다.");
        }
    }
    
    //정적 메소드, 추가!
    static void changeBattery() {
        System.out.println("리모컨 건전지를 교환합니다");
    }
}
public class RemoteControlExmaple {
    public static void main(String[] args) {
        //위 코드 생략
    
        //정적 메소드 호출
        RemoteControl.changeBattery();
    }
}

 

8.7 pritave 메소드

    - private 메소드의 용도 : 디폴트와 정적 메소드들의 중복 코드를 줄이는 것

    - 인터페이스의 상수 필드, 추상 메소드, 디폴트 메소드, 정적 메소드는 모두 public 접근 제한을 가짐
        (해당 멤버들을 선언할 때에는, 생략 시 public -> 외부에서 접근 가능)

        (private 메소드 선언도 가능! -> 외부에서 접근 불가)

private 메소드 - 구현 객체가 필요함
- 디폴트 메소드 안에서만 호출 가능
private 정적 메소드 - 구현 객체가 필요 없는 메소드
- 디폴트 메소드, 정적 메소드 안에서 호출 가능
public interface Service {
    //디폴트 메소드
    default void defaultMethod1() {
        System.out.println("defaultMethod1 종속 코드");
        defaultCommon();
    }
    
    default void defaultMethod2() {
        System.out.println("defaultMethod2 종속 코드");
        defaultCommon();
    }
    
    //private 메소드
    private void defaultCommon() {
        System.out.println("defaultMethod 중복 코드A");
        System.out.println("defaultMethod 중복 코드B");
    }
    
    //정적 메소드
    static void staticMethod1() {
        System.out.println("staticMethod1 종속 코드");
        staticCommon();
    }
    
    static void staticMethod2() {
        System.out.println("staticMethod2 종속 코드");
        staticCommon();
    }
    
    //private 정적 메소드
    private static void staticCommon() {
        System.out.println("staticMethod 중복 코드C");
        System.out.println("staticMethod 중복 코드D");
    }
}
public class ServiceImpl implements Service {
    //추상 메서드가 없으므로 재정의 내용 없음
}
public class ServiceExample {
    public static void main(String[] args) {
        //인터페이스 변수 선언과 구현 객체 대입
        Service service = new ServiceImpl();
        
        //디폴트 메소드 호출
        service.defaultMethod1();
        System.out.println();
        service.defaultMethod2();
        System.out.println();
        
        //정적 메소드 호출 - 구현객체 없이!!
        Service.staticMethod1();
        System.out.println();
        Service.staticMethod2();
        System.out.println();
    }
}

 

'언어 > java' 카테고리의 다른 글

[Java] 8. 인터페이스 (4) - 11~13  (0) 2025.05.26
[Java] 8. 인터페이스 (3) - 8~10  (0) 2025.05.26
[Java] 8. 인터페이스 (1) - 1~3  (0) 2025.05.22
[Java] 7. 상속 (4) - 10~11  (0) 2025.05.22
[Java] 7. 상속 (2) - 5~6  (0) 2025.05.20