@click_f

Что такое «call back interface»?

Кто-нибудь может привести научно-популярный пример и объяснить, что это за свойство интерфейса и для чего оно необходимо?
  • Вопрос задан
  • 451 просмотр
Решения вопроса 2
EvilsInterrupt
@EvilsInterrupt
System programming, Reversing Engineering, C++
Для чего?

Допустим ты пришел в мед.учреждение за справкой по какому-то там специалисту и к примеру справка будет делаться 4 часа. В конечном итоге ее можно будет забрать в регистратуре.

У тебя две стратегии:
1. Каждые 5 мин. подходить в регистратуру "А справка на фамилию Пупкина готова?"
2. Оставить визитную карточку с телефоном на Пупкина и попросить позвонить, как будет готова справка.

Какая стратегия более удобная? ;)

Это принцип "Не звоните нам, мы сами вам позвоним".

Так и в программировании есть некий код, который вызовут при наступлении некоторых условий(сеть доступна, файл появился, кнопку нажали, программа выключается и др.)

Код, который вызывают это callback - "Обратный вызов". Некоторые условия - это событие.

В примере выше callback-ом является Пупкин, а событием является "справка готова".
Ответ написан
Комментировать
pi314
@pi314
Президент Солнечной системы и окрестностей
Если речь о Java и интерфейсах, то пример - как-то так:

interface IObserver {
  void notify(Event e); //I'm a callback  ;)
  ...
}

interface IObservable {
  void register(IObserver o);
  void unregister(IObserver o);
  ...
}


Это не столько свойство интерфейса, сколько паттерн (идея, шаблон) на тему того, как можно в программе организовать взаимодействие (обычно, асинхронное) между двумя сущностями. В данном конкретном примере callback - это метод notify() в первом интерфейсе.

В простейшем случае экземпляр класса, имплементирующего этот интерфейс (наблюдатель) сначала должен зарегистрироваться у какого-нибудь экземпляра, имплементирующего второй (наблюдаемого). После этого, всякий раз, когда в наблюдаемом будет происходить что-то, интересующее наблюдателя, наблюдаемое будет вызывать метод notify() экземпляра наблюдателя (и, например, передавать в него информацию о произошедших изменениях, в виде Event... но это - уже частности, не существенные для понимания сути callback). И так - до тех пор, пока наблюдатель не "попрощается" с наблюдаемым, вызвав его метод unregister(). Кроме того, кто именно "познакомит" одного с другим, тоже не существенно: это может быть сам наблюдатель, или кто-то еще (например, какая-нибудь фабрика, брокер, менеджер и т.д.) Если говорить о "свойствах интерфейса", то суть паттерна состоит в договоренности: "я знаю, что у тебя есть метод, который я могу и буду вызывать, когда сочту нужным, и ты будешь знать, что этот вызов означает". Все остальное (в каком потоке вызывать, что конкретно должен делать этот метод и т.д.) обычно тоже регламентируется, но это, опять же, уже частности.

Для сравнения и отграничения понятия callback (от банальной инкапсуляции и IoC) можно привести пример
java.lang.Comparable<T> {
  int compareTo(T o);
}

Все, что обещает этот интерфейс/метод: "если ты меня вызовешь и передашь мне ссылку на экземпляр такого же класса, как я сам, я сравню себя (по некоему, только мне известному алгоритму) с этим экземпляром и верну результат". Кто его будет вызывать, когда, зачем, что он станет делать с результатом... все это самому имплементирующему классу не важно. Это, хотя и очень похоже, но, строго говоря, не укладывается в понятие callback, т.к. вызываемому методу и всему экземпляру класса, в общем, нет никакого дела до того а. кто его вызовет и б. что это будет означать. А понятие callback подразумевает, что предоставляющий этот метод класс а. знает, кто и зачем его вызовет и б. непосредственно заинтересован в этом.

Ну и, для полноты картины, нужно также упомянуть, что в разных язакых есть много разных способов организации callback. В C# есть делегаты и события, в C можно передать указатель на функцию и т.д. В Java для этого удобно пользоваться интерфейсами. Но это ничего не меняет в самом понятии callback, заключаюшемся в том, что кто-то осознанно предоставляет другому определенный метод, а этот другой этот метод вызывает, и оба знают, что означает сам факт вызова.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
Комментировать
@Braidner
Простой пример
public interface InitCallback {
    void init();

    class Http implements InitCallback {
        void sendData(String url, SuccessCallback success, FailureCallback fail) {
            try {
                //Делаем реквест
                String httpResult = "200";
                //Вызываекм коллбек
                success.success(httpResult);
            } catch (Exception ex) {
                //Вызываекм коллбек в случае ошибки
                fail.fail("400");
            }
        }

        public void init() {
            System.out.println("Вызван init коллбек");
        }

        interface SuccessCallback {
            void success(String result);
        }

        interface FailureCallback {
            void fail(String error);
        }

        public static void main(String[] args) {

            Http http = new Http();
            if (http instanceof InitCallback) {
                //Если это наш интерфес, то вызываем колбек
                http.init();
            }
            
            http.sendData("/my/api", new SuccessCallback() {
                @Override
                public void success(String result) {
                    System.out.println("Успешный колбек: " + result);
                }
            }, new FailureCallback() {
                @Override
                public void fail(String error) {
                    System.out.println("Колбек вернул ошибку: " + error);
                }
            });
        }
    }
}

И по такому же принципу реализуются специальные интерфейсы в спринге. Он смотрит от чего унаследован твой бин и если он знает этот интерфейс, то дергает его.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы