백엔드 수업 #08 인터페이스 - 04 인터페이스 사용

sookyoung.k·2022년 12월 7일
0
post-thumbnail

인터페이스로 구현 객체를 사용하기 위해서는 인터페이스 변수를 선언하고 구현 객체를 대입해야 한다. 여기서 인터페이스 변수는 참조 타입이기 때문에 구현 객체가 대입될 경우 구현 객체의 번지를 저장한다.

public class MyClass {
	//필드
    RemoteControl rc = new Television();
    
    //생성자
    MyClass(RemoteControl rc) {
    	this.rc = rc;
    }
    
    //메소드
    void methodA() {
    	//로컬 변수
        RemoteControl rc = new Audio();
    }
    
    void methodB(RemoteControl rc) { // = mc.methodB(new Audio()); 
    // 매개변수로 RemoteControl 객체를 받는 것임 
    	...
    }
}

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

추상 메소드 사용

구현 객체가 인터페이스 타입에 대입되면 인터페이스에 선언된 추상 메소드를 개발 코드에서 호출할 수 있다!

public class RemoteControlEx {

	public static void main(String[] args) {
		RemoteControl rc = null; // 인터페이스 변수를 선언! 
        
		rc = new Television(); // Television 객체를 인터페이스 타입에 대입하고
		rc.turnOn(); // 인터페이스의 메소드를 호출 
		rc.turnOff();
		
        rc = new Audio(); 
		rc.turnOn();
		rc.turnOff();
	}

}

[출력 결과]
TV를 켭니다.
TV를 끕니다.
오디오를 켭니다.
오디오를 끕니다.

디폴트 메소드 사용

디폴트 메소드는 인터페이스에 선언되지만, 인터페이스에서 바로 사용이 불가하다. 왜?! 냐?! 하?! 면?! 디폴트 메소드는 추상 메소드가 아니기 때문에 객체가 있어야만 사용이 가능하다.

디폴트 메소드는 인터페이스의 모든 구현 객체가 가지고 있는 기본 메소드

물론 디폴트 메소드도 오버라이딩 해서 수정할 수 있다. 그러면 디폴트 메소드가 호출될 때 자신을 재정의한 메소드가 호출된다.

public interface RemoteControl {
	void setVolume(int volume); 
    
	// 디폴트 메소드: 인터페이스에서 실행 메소드를 구현하고 싶을 때 사용
	default void setMute(boolean mute) { // 음소거
		if (mute) {
			System.out.println("음소거 처리 합니다.");
			setVolume(MIN_VOLUME);
		} else {
			System.out.println("음소거 해제");
		}
	}
}

public class Audio implements RemoteControl {
	// 필드
    private boolean mute; 
    private int memoryVolum; // 볼륨을 기억하는 필드 
    
    @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("현재 오디오 볼륨: " + this.volume);
	}

	
	// 디폴트 메소드는 오버라이드 시 반드시 public 접근 제한자를 붙여야 한다. 
	@Override
	public void setMute(boolean mute) {
    	this.mute = mute;
		if(mute) {
			this.memoryVolum = this.volume; // 볼륨값이 memoryVolum에 저장됨
			System.out.println("오디오 무음 처리 합니다."); // 저장 후 "음소거 처리" 출력 
			setVolume(RemoteControl.MIN_VOLUME); // 현재 setVolume을 min상수로 변환 
		} else { 
			System.out.println("오디오 무음 해제합니다.");
			setVolume(this.memoryVolum); // 아까 저장해둔 5를 불러옴 
		}
	}
	
}

public class RemoteControlEx { // 실행 필드 

	public static void main(String[] args) {
		RemoteControl rc = null;

		rc = new Television(); // 자동형변환 일어난 것임(그래서 부모꺼 다 사용 가능)
		rc.setVolume(15); // 오버라이드 된 걸 사용함. 무조건. 
        //(TV 클래스는 귀찮아서 생략함... ㅈㅅ) 
		
		rc.setMute(true);
		rc.setMute(false);
		
		rc = new Audio();
		rc.turnOn();
		rc.setVolume(5);
		
		rc.setMute(true);
		rc.setMute(false);
	}

}

[출력 결과]

현재 TV 볼륨: 15
음소거 처리 합니다
음소거 해제
현재 오디오 볼륨: 15
오디오를 켭니다.
현재 오디오 볼륨: 5
오디오 무음 처리 합니다.
현재 오디오 볼륨: 0
오디오 무음 해제합니다.
현재 오디오 볼륨: 5

정적 메소드 사용

인터페이스의 정적 메소드는 인터페이스로 바로 호출이 가능하다.

public interface RemoteControl {
	// 정적(static) 메소드
	// 코드를 구현할 수 있다. 
	// public이 없어도 컴파일 과정에서 public이 붙는다. 
	static void changeBattery() {
		System.out.println("건전지 교체");
	}
}
public class RemoteControlEx {

	public static void main(String[] args) {
		RemoteControl.changeBattery();
	}

}

RemoteControl의 changeBattery() 정적 메소드를 바로 호출하는 모습.

profile
영차영차 😎

0개의 댓글