Pregunta

¿Cuál es el equivalente Java de los delegados de Cocoa?

(Entiendo que puedo pasar una interfaz a una clase y hacer que esa clase llame a los métodos apropiados, pero me pregunto si hay alguna otra forma de lograr algo más cercano a los protocolos informales de Cocoa / Objective-C)

¿Fue útil?

Solución

La respuesta corta es que no hay nada en Java tan cerca como quisieras, pero hay alternativas. El patrón de delegado no es difícil de implementar, simplemente no es tan conveniente como hacerlo con Objective-C.

La razón "protocolos informales" El trabajo en Objective-C se debe a que el lenguaje admite categorías , que le permiten agregar métodos a las clases existentes sin subclasificarlas, o incluso tener acceso al código fuente. Por lo tanto, la mayoría de los protocolos informales son una categoría en NSObject. Esto es claramente imposible en Java.

Objective-C 2.0 opta por los métodos de protocolo @optional, que es una abstracción mucho más limpia y preferida para el nuevo código, pero aún más lejos de tener un equivalente en Java.

Honestamente, el enfoque más flexible es definir un protocolo delegado, luego hacer que las clases implementen todos los métodos. (Con IDEs modernos como Eclipse, esto es trivial). Muchas interfaces Java tienen una clase de adaptador que lo acompaña, y este es un enfoque común para no requerir que el usuario implemente muchos métodos vacíos, pero restringe la herencia, lo que hace que el diseño del código sea inflexible . (Josh Bloch aborda esto en su libro "Eficaz Java".) Mi sugerencia sería proporcionar solo una interfaz primero, luego agregar un adaptador si es realmente necesario.

Hagas lo que hagas, evita lanzar una UnsupportedOperationException para " no implementado " métodos Esto obliga a la clase delegante a manejar excepciones para métodos que deberían ser opcionales. El enfoque correcto es implementar un método que no hace nada, devuelve un valor predeterminado, etc. Estos valores deben estar bien documentados para los métodos que no tienen un tipo de retorno nulo.

Otros consejos

El mejor análogo a un protocolo informal que se me ocurre es una interfaz que también tiene una clase de adaptador para permitir que los implementadores eviten implementar todos los métodos.

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

Entonces alguien puede venir y simplemente implementar las cosas que les interesan:

class AwesomeDelegate extends MyClassDelegateAdapter {

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

O eso, o puro reflejo llamando "conocido" métodos Pero eso es una locura.

No hay nada que le impida usar el patrón delegado en sus objetos Java (simplemente no es un patrón comúnmente usado en el JDK como lo es en Cocoa). Solo tenga un ivar delegate de un tipo que se ajuste a su interfaz WhateverDelegate , luego, en los métodos de instancia que desea delegar, reenvíe la llamada al método en el objeto delegado si existe . Probablemente terminaría con algo que se parece mucho a esto , excepto en Java en lugar de Obj-C.

En cuanto a las interfaces opcionales, eso sería más difícil. Sugeriría declarar la interfaz, declarar una clase abstracta que implemente métodos opcionales como métodos vacíos, y luego subclasificar la clase abstracta, anulando los métodos opcionales que desea que implemente este objeto en particular. Hay una limitación potencialmente severa aquí debido a la falta de herencia múltiple en Java, pero eso es lo más cercano que se me ocurre.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top