function-pointers listener란 callback - Java의 콜백 함수





8 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 .

인터페이스 액티비티 자바

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

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

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




약간의 질책 :

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

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




흥미있는 리플렉션 라이브러리를 사용하여 구현하는 아이디어를 발견하고이를 생각해 냈습니다. 유일한 단점은 유효한 매개 변수를 전달하고 있는지 컴파일 시간을 잃어 버리는 것입니다.

public class CallBack {
    private String methodName;
    private Object scope;

    public CallBack(Object scope, String methodName) {
        this.methodName = methodName;
        this.scope = scope;
    }

    public Object invoke(Object... parameters) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        Method method = scope.getClass().getMethod(methodName, getParameterClasses(parameters));
        return method.invoke(scope, parameters);
    }

    private Class[] getParameterClasses(Object... parameters) {
        Class[] classes = new Class[parameters.length];
        for (int i=0; i < classes.length; i++) {
            classes[i] = parameters[i].getClass();
        }
        return classes;
    }
}

너는 이렇게 사용한다.

public class CallBackTest {
    @Test
    public void testCallBack() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        TestClass testClass = new TestClass();
        CallBack callBack = new CallBack(testClass, "hello");
        callBack.invoke();
        callBack.invoke("Fred");
    }

    public class TestClass {
        public void hello() {
            System.out.println("Hello World");
        }

        public void hello(String name) {
            System.out.println("Hello " + name);
        }
    }
}



자바에서 이런 종류의 기능이 필요할 때, 나는 보통 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();
    }
}



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



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




Related