Java의 콜백 함수



Answers

Java 8부터 람다 및 메소드 참조가 있습니다.

예를 들어 다음과 같이 정의 할 수 있습니다.

public class FirstClass {
    String prefix;
    public FirstClass(String prefix){
        this.prefix = prefix;
    }
    public String addPrefix(String suffix){
        return prefix +":"+suffix;
    }
}

import java.util.function.Function;

public class SecondClass {
    public String applyFunction(String name, Function<String,String> function){
        return function.apply(name);
    }
}

그럼 당신은 할 수 있습니다 :

FirstClass first = new FirstClass("first");
SecondClass second = new SecondClass();
System.out.println(second.applyFunction("second",first::addPrefix));

github에 대한 예제는 다음을 참조하십시오. julien-diener/MethodReference .

Question

Java 메소드에서 콜백 함수를 전달하는 방법이 있습니까?

내가 흉내 내려고 시도하는 동작은 .Net Delegate가 함수에 전달된다는 것입니다.

나는 사람들이 별도의 객체를 만드는 것을 제안했지만 잔인한 것처럼 보였지 만 때로는 잔인 함이 일을하는 유일한 방법이라는 것을 알고 있습니다.




이것은 람다가있는 Java 8에서 매우 쉽습니다.

public interface Callback {
    void callback();
}

public class Main {
    public static void main(String[] args) {
        methodThatExpectsACallback(() -> System.out.println("I am the callback."));
    }
    private static void methodThatExpectsACallback(Callback callback){
        System.out.println("I am the method.");
        callback.callback();
    }
}



또한 Delegate 패턴을 사용하여 Callback 을 수행 할 수 있습니다.

Callback.java

public interface Callback {
    void onItemSelected(int position);
}

PagerActivity.java

public class PagerActivity implements Callback {

    CustomPagerAdapter mPagerAdapter;

    public PagerActivity() {
        mPagerAdapter = new CustomPagerAdapter(this);
    }

    @Override
    public void onItemSelected(int position) {
        // Do something
        System.out.println("Item " + postion + " selected")
    }
}

CustomPagerAdapter.java

public class CustomPagerAdapter {
    private static final int DEFAULT_POSITION = 1;
    public CustomPagerAdapter(Callback callback) {
        callback.onItemSelected(DEFAULT_POSITION);
    }
}



제 생각에는 추상 클래스를 사용하는 것이 더 우아합니다.

// Something.java

public abstract class Something {   
    public abstract void test();        
    public void usingCallback() {
        System.out.println("This is before callback method");
        test();
        System.out.println("This is after callback method");
    }
}

// CallbackTest.java

public class CallbackTest extends Something {
    @Override
    public void test() {
        System.out.println("This is inside CallbackTest!");
    }

    public static void main(String[] args) {
        CallbackTest myTest = new CallbackTest();
        myTest.usingCallback();
    }    
}

/*
Output:
This is before callback method
This is inside CallbackTest!
This is after callback method
*/



자바에서 이런 종류의 기능이 필요할 때, 나는 보통 Observer 패턴을 사용한다. 그것은 여분의 객체를 의미하지만, 그것은 깨끗한 방법이라고 생각하며, 코드 가독성을 높이는 널리 이해되는 패턴입니다.




약간의 질책 :

나는 사람들이 별도의 객체를 만드는 것을 제안하는 것 같지만 과도하게 보인다.

콜백을 전달하는 것은 상당히 많은 OO 언어로 별도의 객체를 생성하는 것을 포함하므로 지나치게 과장된 것으로 간주 될 수 없습니다. 아마도 Java에서 명시적인 일류 함수 또는 클로저를 사용하는 언어보다 더 자세한 (그리고 리소스 집약적 인) 별도의 클래스를 만들어야합니다. 그러나 익명 클래스는 최소한의 자세한 정보를 줄이고 인라인으로 사용할 수 있습니다.




public class HelloWorldAnonymousClasses {

    //this is an interface with only one method
    interface HelloWorld {
        public void printSomething(String something);
    }

    //this is a simple function called from main()
    public void sayHello() {

    //this is an object with interface reference followed by the definition of the interface itself

        new HelloWorld() {
            public void printSomething(String something) {
                System.out.println("Hello " + something);
            }
        }.printSomething("Abhi");

     //imagine this as an object which is calling the function'printSomething()"
    }

    public static void main(String... args) {
        HelloWorldAnonymousClasses myApp =
                new HelloWorldAnonymousClasses();
        myApp.sayHello();
    }
}
//Output is "Hello Abhi"

기본적으로 인터페이스의 객체를 만들고 싶다면 인터페이스가 객체를 가질 수 없으므로 불가능합니다.

옵션은 어떤 클래스가 인터페이스를 구현하게하고 그 클래스의 객체를 사용하여 그 함수를 호출하는 것이다. 그러나이 방법은 매우 장황합니다.

또는 새로운 HelloWorld ()를 작성한 다음 (* 클래스가 아닌 인터페이스 임) 인터페이스 메소드 자체의 정의를 따르십시오. (*이 정의는 실제로 익명의 클래스이다.) 그런 다음 메서드 참조를 통해 개체 참조를 가져옵니다.




아직 나는이 답변에서 파생 된 것이 무엇인지 찾고있는 가장 선호되는 방법이 있다는 것을 알지만, 나는 그것을 더 복잡하고 효율적으로 조작해야만했다. 그리고 나는 모두가 내가 생각해내는 것을 찾고 있다고 생각한다 .

요점 :

먼저 인터페이스 를 단순 하게 만든다.

public interface myCallback {
    void onSuccess();
    void onError(String err);
}

이제는이 콜백을 실행하여 결과를 처리하기를 원할 때 - 비동기 호출 이후에 더 많은 가능성이 있고 이러한 재진입에 의존하는 일부 항목을 실행하고 싶습니다.

// import the Interface class here

public class App {

    public static void main(String[] args) {
        // call your method
        doSomething("list your Params", new myCallback(){
            @Override
            public void onSuccess() {
                // no errors
                System.out.println("Done");
            }

            @Override
            public void onError(String err) {
                // error happen
                System.out.println(err);
            }
        });
    }

    private void doSomething(String param, // some params..
                             myCallback callback) {
        // now call onSuccess whenever you want if results are ready
        if(results_success)
            callback.onSuccess();
        else
            callback.onError(someError);
    }

}

doSomething 은 결과가 왔을 때 알려주기 위해 콜백을 추가하는 데 시간이 걸리는 함수입니다. 콜백 인터페이스를 매개 변수로이 메소드에 추가하십시오.

내 요점이 분명히 희망, 즐기십시오;)




Links