Java-эквивалент делегатов Какао / Неофициальные протоколы Objective-C?

StackOverflow https://stackoverflow.com/questions/1209943

Вопрос

Что такое Java-эквивалент делегатов Какао?

(я понимаю, что я могу передать интерфейс в класс и заставить этот класс вызывать соответствующие методы, но мне интересно, есть ли другой способ достичь чего-то более близкого к неофициальным протоколам Cocoa / Objective-C)

Это было полезно?

Решение

Короткий ответ: в Java нет ничего более близкого, чем хотелось бы, но есть альтернативы. Шаблон делегата не сложно реализовать, просто он не так удобен, как при использовании Objective-C.

Причина "неофициальных протоколов" Работа в Objective-C объясняется тем, что язык поддерживает категории , которые позволяют добавлять методы к существующим классам, не разбивая их на подклассы или даже не имея доступа к исходному коду. Таким образом, большинство неформальных протоколов являются категорией на NSObject. Это явно невозможно в Java.

Objective-C 2.0 выбирает методы @optional протокола, который является намного более чистой абстракцией и предпочтителен для нового кода, но еще дальше от аналога в Java.

Честно говоря, наиболее гибкий подход заключается в определении протокола делегата, а затем в классах реализуют все методы. (В современных IDE, таких как Eclipse, это тривиально.) Многие интерфейсы Java имеют сопутствующий класс адаптера, и это общий подход, при котором пользователю не требуется реализовывать много пустых методов, но он ограничивает наследование, что делает дизайн кода негибким , (Джош Блох рассматривает это в своей книге «Эффективная Java».) Я бы предложил сначала предоставить только интерфейс, а затем добавить адаптер, если это действительно необходимо.

Что бы вы ни делали, не добавляйте UnsupportedOperationException для " не реализованного " методы. Это заставляет делегирующий класс обрабатывать исключения для методов, которые должны быть необязательными. Правильный подход - реализовать метод, который ничего не делает, возвращает значение по умолчанию и т. Д. Эти значения должны быть хорошо документированы для методов, которые не имеют возвращаемого типа void.

Другие советы

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

public class MyClass {

    private MyClassDelegate delegate;

    public MyClass () {

    }

    // do interesting stuff

    void setDelegate(MyClassDelegate delegate) {
        this.delegate = delegate;
    }

    interface MyClassDelegate {
        void aboutToDoSomethingAwesome();
        void didSomethingAwesome();
    }

    class MyClassDelegateAdapter implements MyClassDelegate {

        @Override
        public void aboutToDoSomethingAwesome() {
            /* do nothing */
        }

        @Override
        public void didSomethingAwesome() {
            /* do nothing */
        }
    }
}

Тогда кто-то может прийти и просто реализовать то, что ему небезразлично:

class AwesomeDelegate extends MyClassDelegateAdapter {

    @Override
    public void didSomethingAwesome() {
        System.out.println("Yeah!");
    }
}

Либо это, либо чистое отражение, называющее "известным" методы. Но это безумие.

Ничто не мешает вам использовать шаблон делегата в ваших объектах Java (это просто не часто используемый шаблон в JDK, как в Какао). Просто имейте ивару делегат типа, который соответствует вашему интерфейсу WhwhatDelegate , а затем в методах вашего экземпляра, которым вы хотите делегировать, перенаправьте вызов метода на объект делегата, если он существует , Возможно, в конечном итоге вы получите нечто, похожее на это , за исключением Java вместо Obj-C.

Что касается необязательных интерфейсов, это будет сложнее. Я бы предложил объявить интерфейс, объявить абстрактный класс, который реализует необязательные методы как пустые методы, а затем создать подкласс класса абстрактного класса, переопределяя необязательные методы, которые вы хотите реализовать в данном конкретном объекте. Здесь существует потенциально серьезное ограничение из-за отсутствия множественного наследования в Java, но это настолько близко, насколько я могу придумать.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top