Java의 콜백 함수


7 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가 함수에 전달된다는 것입니다.

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




또한 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);
    }
}



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




이것은 람다가있는 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();
    }
}



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




약간의 질책 :

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

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




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

// 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
*/



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

요점 :

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

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

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




Related