본문 바로가기

Programming/JAVA

중첩 클래스&인터페이스(4) - 중첩 인터페이스

java logo image

 

 

 

중첩 인터페이스는 클래스 내부에 멤버로서 선언된 인터페이스를 의미합니다. 일단 중첩 형태로 인터페이스를 선언하게 되는 경우는, 해당되는 바깥 클래스와 밀접하게 연결된 구현 클래스를 생성하기 위함입니다. 주로 UI 처리 관련 코드에서 사용하게 되는데 자세한 것은 차차 살펴보도록 하겠습니다. 

 

기본적인 형태는 다음과 같습니다.

 

class Outter {
    interface I {
        void method();
    }
}

 

 


 

 

안드로이드 스튜디오 등에서 UI 관련 이벤트를 구현할 때 자주 사용되는 패턴을 통해서, 중첩 인터페이스의 사용 방식을 알아보겠습니다. 일단 Button이라는 클래스가 있고, 이 클래스를 통해서 우리가 '클릭'이 발생했을 때의 여러가지 동작을 정의하는 상황이라고 가정해 보겠습니다. 

 

예를 들어 Button 클래스를 통해서 [전화걸기] 버튼, 그리고 [메시지 보내기] 버튼을 각각 두 개를 만들었다고 생각해 보겠습니다. [전화걸기] 버튼을 클릭하면 당연히 전화를 거는 동작을 실행해야 하고, [메시지 보내기] 버튼을 클릭하면 메시지 보내는 동작이 이루어져야 합니다. 

 

이때, Button 클래스 내부에는 OnClickListener라는 중첩 인터페이스가 있고 여기서는 onClick이라는 메서드가 선언되어 있습니다. 이 onClick 메서드는 '클릭이 일어났을 때의 동작'을 구현하게 됩니다. 그럼 이 Button 내부의 OnClickListener 인터페이스를 구현하는 전화걸기 클래스와 메시지 보내기 클래스를 선언하고, 각각 onClick의 동작을 정의합니다.

 

기본적인 구조는 설명하였으니, 아래의 예제를 통해서 살펴보겠습니다. 

 

public class Button {
	OnClickListener listener;
	
	void setOnClickListener(OnClickListener listener) {
		this.listener = listener;
	}
	
	void touch() {
		listener.onClick();
	}
	
	interface OnClickListener {
		void onClick();
	}
}

 

Button 클래스 내부에 OnClickListener 인터페이스가 중첩 선언되어 있고, onClick 메서드를 구현하도록 되어있습니다. 어떤 클래스가 이 중첩 인터페이스를 구현하여 onClick을 재정의 해두었다면, 해당 구현 클래스를 setOnClickListener를 이용해 Button 클래스 인스턴스의 필드로 대입하게 되죠.

 

그리고 그 Button 클래스의 인스턴스에서 touch 메서드를 실행하게 되면 해당 구현 클래스가 가진 onClick을 실행하게 되는 구조입니다. 다소 복잡해 보이지만, Button이라는 인터페이스와 클릭하는 이벤트를 긴밀하고 예외없이 구현하기 위한 구조이니 잘 기억해 두셔야 합니다. 

 

public class PhoneListener implements Button.OnClickListener {
	@Override
	public void onClick() {
		System.out.println("전화 걸기 실행");
	}
}

 

public class MsgListener implements Button.OnClickListener{
	@Override
	public void onClick() {
		System.out.println("메시지 전송 실행");
	}
}

 

위와 같이 OnClickListener를 구현한 구현 클래스 두 개를 생성해 보았습니다. 이제 두 개의 구현 클래스는 Button 클래스에 setOnClickListener의 파라미터로 전달되어 Button 클래스 내부에서 사용하게 됩니다.

 

public class ExampleMain {	
	public static void main(String[] args) {
		Button btn = new Button();
		
		btn.setOnClickListener(new PhoneListener());
		btn.touch();
		
		btn.setOnClickListener(new MsgListener());
		btn.touch();
	}
}

/* 출력
전화 걸기 실행
메시지 전송 실행
*/

 

 

 


 

 

 

다시 한번 위 내용을 복습하면서 정리하겠습니다. 만일 아래 내용을 읽으면서 인터페이스의 기본 사용법이 헷갈린다면 기본 인터페이스 예제인 'Tire' 예제를 참고하시면서 따라가시기 바랍니다.

 

 

인터페이스(8) - 인터페이스의 타입 변환과 다형성 2

○ 자동 타입 변환(promotion) 상속 체계 하에서의 타입 변환과 마찬가지로, 구현 객체가 자식 클래스의 포지션에서 인터페이스 타입으로 변환되는 것이 자동 타입 변환에 해당하게 됩니다. 여기는

nozeroslope.tistory.com

 

1. 우선, Button클래스 내부에 선언된 OnClickListener라는 인터페이스가 있습니다. 중첩 인터페이스라는 생각은 잠시 접어두겠습니다. 

2. 이 OnClickListener라는 인터페이스에 선언된 메서드는 onClick( ) 입니다. 당연히 이를 사용하기 위해서는 구현 클래스가 필요합니다. 여기서 OnClickListenr라는 인터페이스가 Tire의 포지션이고, onClick( )은 roll( ) 포지션이 되겠네요.

3. OnClickListenr 구현 클래스는 PhoneListener, MsgListener로 선언하겠습니다. KumhoTire, HankookTire 포지션이 되겠네요. 이 구현 클래스들은 Button.OnClickListener라는 인터페이스를 implements하여 구현하고 onClick( )이라는 메서드를 오버라이드 합니다. 

4.  지금부터가 중요합니다. Button이라는 클래스의 작동 원리를 설명하겠습니다. 우선, 안드로이드에서는 Button 클래스의 인스턴스를 생성하여 여러가지 버튼들의 동작을 선언합니다. View 클래스도 마찬가지죠. 이 Button 클래스 내부에 중첩 인터페이스로 OnClickListener가 선언되어 있는 상태입니다. 

5. 이 Button 클래스의 인스턴스 상에서 touch( )라는 메서드가 실행되면, 각각의 OnClickListener의 구현 클래스에 따라서 오버라이드 된 onClick( ) 메서드가 실행되게 하려고 합니다. 예를 들어 스마트폰 버튼인 btn1.touch( )를 실행했을 때와 문자 전송 기능을 담당하는 버튼인 btn2.touch( )를 실행했을 때 차이를 두기 위해서죠.

6. 그래서 Button 클래스는 이 중첩 인터페이스인 OnClickListener 인스턴스를 파라미터로 받는 setOnClickListener(OnClickListener listenr)라는 메서드를 갖고 있습니다. 잘 생각하면 이 메서드는 기초 예제에서 아래 라인과 같은 역할을 합니다. 

Tire frontLeftTire = new HankookTire( );

7. 그래서 특정 버튼을 터치하면 btn.touch( )라는 메서드가 실행되고(이는 OS상에서 정해진 동작 규범), 각 Button 인스턴스에서 touch( )가 실행되면 본인 인스턴스에 할당된 OnClickListener가 가진 onClick( )을 실행하게 되는 것입니다.