반응형

자바 interface로 구현된 라이브러리를 상속받아 사용하던 중 특정 메소드가 수신받으면 동작하는 메소드가 존재하였습니다.

 

메인문에서 해당 메소드가 동작하는 것을 감지하고 싶었고, 찾아본 내용은 콜백함수였습니다.

그 동안 사용한 interface의 특징을 제대로 파악하지 못하고 기능을 제대로 사용하지 못하고 있다는걸 느끼게 되었습니다.

 

 

콜백을 공부하면서 CALLER(호출자), CALLEE(피호출자)로 불리는 단어가 존재하였는데, 해당 단어를 가지고 정리를 하면 다음과 같습니다.

일반적인 호출 CALLER가 CALLEE에게 요청하여 수행

콜백 CALLEE가 CALLER에게 요청으로 이해하시면 될 것 같습니다.

 

 


관련 예제를 확인해보겠습니다. Scanner를 통해 메시지를 입력받고 콜백함수를 호출해보겠습니다.

 

CallBack

Interface를 활용하여 콜백 구현하기

Callee.java

package com.psw.callback;

import java.util.Scanner;

public class Callee {
	private String msg;
	private CallBack callback;
	
	@FunctionalInterface
	public interface CallBack{
		public void onGetMessage(Callee callee);
	}
	
	public Callee() {
		this.msg = "";
		this.callback = null;
	}

	public String getMsg() {
		return msg;
	}

	public void setCallback(CallBack callback) {
		this.callback = callback;
	}
	
	public void onInputMessage() {
		Scanner scanner = new Scanner(System.in);
		this.msg = ""; //초기화
		System.out.print("메시지를 입력하세요 : ");
		this.msg = scanner.nextLine();
		
		if(this.callback != null) { //callback처리
			this.callback.onGetMessage(Callee.this);
		}
	}
}

 

CallBack.java

package com.psw.callback;

public class CallBack {

	public static void main(String[] args) {
		Callee callee = new Callee();
		callee.setCallback(new Callee.CallBack() {
			
			@Override
			public void onGetMessage(Callee callee) {
				//callback
				System.out.println("입력받은 메시지 >" + callee.getMsg());
			}
		});
		
		for(int i=0; i<5; i++){ //메시지 발송을 5번까지 보낸다
			callee.onInputMessage();
		}
	}

}

 

callback이 null이 아니면 onGetMessage를 수행하고 전달합니다.

메시지를 입력해보겠습니다.

잘받아지는 모습!

메시지를 입력하는 함수만 동작시키고 있지만 override 처리한 onGetMessage에서 콜백 동작을 하면서 정상적으로 메시지를 받는 모습을 볼 수 있습니다.

 

 


Functional Interface 방식으로 구현하기

동일한 동작이지만 java8에서 추가된 함수형 인터페이스를 사용한 표현방법을 알아보겠습니다.

 

Callee.java

package com.psw.callback;

import java.util.Scanner;
import java.util.function.Consumer;


public class Callee {
	private String msg;
	private Consumer<Callee> callback;
	
	public Callee() {
		this.msg = "";
		this.callback = null;
	}

	public String getMsg() {
		return msg;
	}

	public void setCallback(Consumer<Callee> callback) {
		this.callback = callback;
	}

	public void onInputMessage() {
		Scanner scanner = new Scanner(System.in);
		this.msg = ""; //초기화
		System.out.print("메시지를 입력하세요 : ");
		this.msg = scanner.nextLine();
		
		if(this.callback != null) { //callback처리
			this.callback.accept(Callee.this);
		}
	}
}

 

CallBack.java

package com.psw.callback;

public class CallBack {

	public static void main(String[] args) {
		Callee callee = new Callee();
		callee.setCallback((arg)->{
			System.out.println(arg.getMsg());
		});
		
		for(int i=0; i<5; i++){ //메시지 발송을 5번까지 보낸다
			callee.onInputMessage();
		}
	}
}

 

동일한 동작이지만 정의부분이나 사용부분이 많이 간결해진 것을 볼 수 있습니다.

리턴값이 없는 메소드였기때문에 Consumer를 사용하여 정의하였고, 람다식을 통해 인자값만 넘겨주어 바로 표현식으로 sysout처리를 하였습니다.

 

동일하게 잘 작동!

 

반응형